aboutsummaryrefslogtreecommitdiff
path: root/src/util
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2013-07-18 13:45:05 +0000
committerChristian Grothoff <christian@grothoff.org>2013-07-18 13:45:05 +0000
commit250751135454656057d1a8d877e698a93c7002be (patch)
tree338d785a81142e5809f2f3711d62f85ddb9c6399 /src/util
parent23b28da68bbca9dcd677cdd96473fd18e90e5a7e (diff)
downloadgnunet-250751135454656057d1a8d877e698a93c7002be.tar.gz
gnunet-250751135454656057d1a8d877e698a93c7002be.zip
-removing last bits of RSA support, as this code is now dead
Diffstat (limited to 'src/util')
-rw-r--r--src/util/Makefile.am24
-rw-r--r--src/util/crypto_ksk.c632
-rw-r--r--src/util/crypto_rsa.c1386
-rw-r--r--src/util/gnunet-rsa.c138
-rw-r--r--src/util/test_crypto_ksk.c261
-rw-r--r--src/util/test_crypto_rsa.c352
6 files changed, 0 insertions, 2793 deletions
diff --git a/src/util/Makefile.am b/src/util/Makefile.am
index 44e22e390..17c06ddbd 100644
--- a/src/util/Makefile.am
+++ b/src/util/Makefile.am
@@ -81,9 +81,7 @@ libgnunetutil_la_SOURCES = \
81 crypto_hash.c \ 81 crypto_hash.c \
82 crypto_hkdf.c \ 82 crypto_hkdf.c \
83 crypto_kdf.c \ 83 crypto_kdf.c \
84 crypto_ksk.c \
85 crypto_random.c \ 84 crypto_random.c \
86 crypto_rsa.c \
87 disk.c \ 85 disk.c \
88 disk.h \ 86 disk.h \
89 getopt.c \ 87 getopt.c \
@@ -136,7 +134,6 @@ bin_PROGRAMS = \
136 gnunet-resolver \ 134 gnunet-resolver \
137 gnunet-config \ 135 gnunet-config \
138 $(GNUNET_ECC) \ 136 $(GNUNET_ECC) \
139 gnunet-rsa \
140 gnunet-uri 137 gnunet-uri
141 138
142 139
@@ -158,15 +155,6 @@ gnunet_resolver_DEPENDENCIES = \
158 libgnunetutil.la 155 libgnunetutil.la
159 156
160 157
161gnunet_rsa_SOURCES = \
162 gnunet-rsa.c
163gnunet_rsa_LDADD = \
164 $(top_builddir)/src/util/libgnunetutil.la \
165 $(GN_LIBINTL) -lgcrypt
166gnunet_rsa_DEPENDENCIES = \
167 libgnunetutil.la
168
169
170gnunet_ecc_SOURCES = \ 158gnunet_ecc_SOURCES = \
171 gnunet-ecc.c 159 gnunet-ecc.c
172gnunet_ecc_LDADD = \ 160gnunet_ecc_LDADD = \
@@ -226,9 +214,7 @@ check_PROGRAMS = \
226 test_crypto_ecc \ 214 test_crypto_ecc \
227 test_crypto_hash \ 215 test_crypto_hash \
228 test_crypto_hkdf \ 216 test_crypto_hkdf \
229 test_crypto_ksk \
230 test_crypto_random \ 217 test_crypto_random \
231 test_crypto_rsa \
232 test_disk \ 218 test_disk \
233 test_getopt \ 219 test_getopt \
234 test_connection \ 220 test_connection \
@@ -369,21 +355,11 @@ test_crypto_hkdf_SOURCES = \
369test_crypto_hkdf_LDADD = \ 355test_crypto_hkdf_LDADD = \
370 $(top_builddir)/src/util/libgnunetutil.la 356 $(top_builddir)/src/util/libgnunetutil.la
371 357
372test_crypto_ksk_SOURCES = \
373 test_crypto_ksk.c
374test_crypto_ksk_LDADD = \
375 $(top_builddir)/src/util/libgnunetutil.la
376
377test_crypto_random_SOURCES = \ 358test_crypto_random_SOURCES = \
378 test_crypto_random.c 359 test_crypto_random.c
379test_crypto_random_LDADD = \ 360test_crypto_random_LDADD = \
380 $(top_builddir)/src/util/libgnunetutil.la 361 $(top_builddir)/src/util/libgnunetutil.la
381 362
382test_crypto_rsa_SOURCES = \
383 test_crypto_rsa.c
384test_crypto_rsa_LDADD = \
385 $(top_builddir)/src/util/libgnunetutil.la
386
387test_disk_SOURCES = \ 363test_disk_SOURCES = \
388 test_disk.c 364 test_disk.c
389test_disk_LDADD = \ 365test_disk_LDADD = \
diff --git a/src/util/crypto_ksk.c b/src/util/crypto_ksk.c
deleted file mode 100644
index 0c091099e..000000000
--- a/src/util/crypto_ksk.c
+++ /dev/null
@@ -1,632 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 1994, 1996, 1998, 2001, 2002, 2003 Free Software Foundation, Inc.
4 Copyright (C) 2004, 2005, 2006 Christian Grothoff (and other contributing authors)
5
6 GNUnet is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published
8 by the Free Software Foundation; either version 2, or (at your
9 option) any later version.
10
11 GNUnet is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNUnet; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA.
20
21 Note: This code is based on code from libgcrypt
22 The code was adapted for GNUnet to support RSA-key generation
23 based on weak, pseudo-random keys. Do NOT use to generate
24 ordinary RSA keys!
25*/
26
27
28/**
29 * @file util/crypto_ksk.c
30 * @brief implementation of RSA-Key generation for KBlocks
31 * (do NOT use for pseudonyms or hostkeys!)
32 * @author Christian Grothoff
33 */
34
35#include "platform.h"
36#include "gnunet_common.h"
37#include "gnunet_crypto_lib.h"
38#include "gnunet_os_lib.h"
39#include <gcrypt.h>
40#include <limits.h>
41
42#define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__)
43
44/**
45 * Log an error message at log-level 'level' that indicates
46 * a failure of the command 'cmd' with the message given
47 * by gcry_strerror(rc).
48 */
49#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);
50
51
52typedef struct
53{
54 gcry_mpi_t n; /* public modulus */
55 gcry_mpi_t e; /* public exponent */
56 gcry_mpi_t d; /* exponent */
57 gcry_mpi_t p; /* prime p. */
58 gcry_mpi_t q; /* prime q. */
59 gcry_mpi_t u; /* inverse of p mod q. */
60} KBlock_secret_key;
61
62/**
63 * The private information of an RSA key pair.
64 * NOTE: this must match the definition in crypto_rsa.c
65 */
66struct GNUNET_CRYPTO_RsaPrivateKey
67{
68 gcry_sexp_t sexp;
69};
70
71
72static void
73mpz_randomize (gcry_mpi_t n, unsigned int nbits, struct GNUNET_HashCode * rnd)
74{
75 struct GNUNET_HashCode hc;
76 struct GNUNET_HashCode tmp;
77 int bits_per_hc = sizeof (struct GNUNET_HashCode) * 8;
78 int cnt;
79 int i;
80
81 GNUNET_assert (nbits > 0);
82 cnt = (nbits + bits_per_hc - 1) / bits_per_hc;
83 gcry_mpi_set_ui (n, 0);
84
85 tmp = *rnd;
86 for (i = 0; i < cnt; i++)
87 {
88 int j;
89
90 if (i > 0)
91 GNUNET_CRYPTO_hash (&hc, sizeof (struct GNUNET_HashCode), &tmp);
92 for (j = 0; j < sizeof (struct GNUNET_HashCode) / sizeof (uint32_t); j++)
93 {
94#if HAVE_GCRY_MPI_LSHIFT
95 gcry_mpi_lshift (n, n, sizeof (uint32_t) * 8);
96#else
97 gcry_mpi_mul_ui (n, n, 1 << (sizeof (uint32_t) * 4));
98 gcry_mpi_mul_ui (n, n, 1 << (sizeof (uint32_t) * 4));
99#endif
100 gcry_mpi_add_ui (n, n, ntohl (((uint32_t *) & tmp)[j]));
101 }
102 hc = tmp;
103 }
104 GNUNET_CRYPTO_hash (&hc, sizeof (struct GNUNET_HashCode), rnd);
105 i = gcry_mpi_get_nbits (n);
106 while (i > nbits)
107 gcry_mpi_clear_bit (n, --i);
108}
109
110static unsigned long
111mpz_trailing_zeroes (gcry_mpi_t n)
112{
113 unsigned int idx, cnt;
114
115 cnt = gcry_mpi_get_nbits (n);
116 for (idx = 0; idx < cnt; idx++)
117 {
118 if (gcry_mpi_test_bit (n, idx) == 0)
119 return idx;
120 }
121
122 return ULONG_MAX;
123}
124
125static void
126mpz_tdiv_q_2exp (gcry_mpi_t q, gcry_mpi_t n, unsigned int b)
127{
128 gcry_mpi_t u, d;
129
130 u = gcry_mpi_set_ui (NULL, 1);
131 d = gcry_mpi_new (0);
132 gcry_mpi_mul_2exp (d, u, b);
133 gcry_mpi_div (q, NULL, n, d, 0);
134}
135
136/**
137 * Return true if n is probably a prime
138 */
139static int
140is_prime (gcry_mpi_t n, int steps, struct GNUNET_HashCode * hc)
141{
142 gcry_mpi_t x;
143 gcry_mpi_t y;
144 gcry_mpi_t z;
145 gcry_mpi_t nminus1;
146 gcry_mpi_t a2;
147 gcry_mpi_t q;
148 unsigned int i, j, k;
149 int rc = 0;
150 unsigned int nbits;
151
152 x = gcry_mpi_new (0);
153 y = gcry_mpi_new (0);
154 z = gcry_mpi_new (0);
155 nminus1 = gcry_mpi_new (0);
156 a2 = gcry_mpi_set_ui (NULL, 2);
157
158 nbits = gcry_mpi_get_nbits (n);
159 gcry_mpi_sub_ui (nminus1, n, 1);
160
161 /* Find q and k, so that n = 1 + 2^k * q . */
162 q = gcry_mpi_set (NULL, nminus1);
163 k = mpz_trailing_zeroes (q);
164 mpz_tdiv_q_2exp (q, q, k);
165
166 for (i = 0; i < steps; i++)
167 {
168 if (!i)
169 {
170 gcry_mpi_set_ui (x, 2);
171 }
172 else
173 {
174 mpz_randomize (x, nbits - 1, hc);
175 GNUNET_assert (gcry_mpi_cmp (x, nminus1) < 0);
176 GNUNET_assert (gcry_mpi_cmp_ui (x, 1) > 0);
177 }
178 gcry_mpi_powm (y, x, q, n);
179 if (gcry_mpi_cmp_ui (y, 1) && gcry_mpi_cmp (y, nminus1))
180 {
181 for (j = 1; j < k && gcry_mpi_cmp (y, nminus1); j++)
182 {
183 gcry_mpi_powm (y, y, a2, n);
184 if (!gcry_mpi_cmp_ui (y, 1))
185 goto leave; /* Not a prime. */
186 }
187 if (gcry_mpi_cmp (y, nminus1))
188 goto leave; /* Not a prime. */
189 }
190 }
191 rc = 1; /* May be a prime. */
192
193leave:
194 gcry_mpi_release (x);
195 gcry_mpi_release (y);
196 gcry_mpi_release (z);
197 gcry_mpi_release (nminus1);
198 gcry_mpi_release (q);
199 gcry_mpi_release (a2);
200
201 return rc;
202}
203
204/**
205 * If target != size, move target bytes to the
206 * end of the size-sized buffer and zero out the
207 * first target-size bytes.
208 */
209static void
210adjust (unsigned char *buf, size_t size, size_t target)
211{
212 if (size < target)
213 {
214 memmove (&buf[target - size], buf, size);
215 memset (buf, 0, target - size);
216 }
217}
218
219
220static void
221gen_prime (gcry_mpi_t * ptest, unsigned int nbits, struct GNUNET_HashCode * hc)
222{
223 /* Note: 2 is not included because it can be tested more easily by
224 * looking at bit 0. The last entry in this list is marked by a zero */
225 static const uint16_t small_prime_numbers[] = {
226 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43,
227 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101,
228 103, 107, 109, 113, 127, 131, 137, 139, 149, 151,
229 157, 163, 167, 173, 179, 181, 191, 193, 197, 199,
230 211, 223, 227, 229, 233, 239, 241, 251, 257, 263,
231 269, 271, 277, 281, 283, 293, 307, 311, 313, 317,
232 331, 337, 347, 349, 353, 359, 367, 373, 379, 383,
233 389, 397, 401, 409, 419, 421, 431, 433, 439, 443,
234 449, 457, 461, 463, 467, 479, 487, 491, 499, 503,
235 509, 521, 523, 541, 547, 557, 563, 569, 571, 577,
236 587, 593, 599, 601, 607, 613, 617, 619, 631, 641,
237 643, 647, 653, 659, 661, 673, 677, 683, 691, 701,
238 709, 719, 727, 733, 739, 743, 751, 757, 761, 769,
239 773, 787, 797, 809, 811, 821, 823, 827, 829, 839,
240 853, 857, 859, 863, 877, 881, 883, 887, 907, 911,
241 919, 929, 937, 941, 947, 953, 967, 971, 977, 983,
242 991, 997, 1009, 1013, 1019, 1021, 1031, 1033,
243 1039, 1049, 1051, 1061, 1063, 1069, 1087, 1091,
244 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151,
245 1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213,
246 1217, 1223, 1229, 1231, 1237, 1249, 1259, 1277,
247 1279, 1283, 1289, 1291, 1297, 1301, 1303, 1307,
248 1319, 1321, 1327, 1361, 1367, 1373, 1381, 1399,
249 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451,
250 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493,
251 1499, 1511, 1523, 1531, 1543, 1549, 1553, 1559,
252 1567, 1571, 1579, 1583, 1597, 1601, 1607, 1609,
253 1613, 1619, 1621, 1627, 1637, 1657, 1663, 1667,
254 1669, 1693, 1697, 1699, 1709, 1721, 1723, 1733,
255 1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789,
256 1801, 1811, 1823, 1831, 1847, 1861, 1867, 1871,
257 1873, 1877, 1879, 1889, 1901, 1907, 1913, 1931,
258 1933, 1949, 1951, 1973, 1979, 1987, 1993, 1997,
259 1999, 2003, 2011, 2017, 2027, 2029, 2039, 2053,
260 2063, 2069, 2081, 2083, 2087, 2089, 2099, 2111,
261 2113, 2129, 2131, 2137, 2141, 2143, 2153, 2161,
262 2179, 2203, 2207, 2213, 2221, 2237, 2239, 2243,
263 2251, 2267, 2269, 2273, 2281, 2287, 2293, 2297,
264 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357,
265 2371, 2377, 2381, 2383, 2389, 2393, 2399, 2411,
266 2417, 2423, 2437, 2441, 2447, 2459, 2467, 2473,
267 2477, 2503, 2521, 2531, 2539, 2543, 2549, 2551,
268 2557, 2579, 2591, 2593, 2609, 2617, 2621, 2633,
269 2647, 2657, 2659, 2663, 2671, 2677, 2683, 2687,
270 2689, 2693, 2699, 2707, 2711, 2713, 2719, 2729,
271 2731, 2741, 2749, 2753, 2767, 2777, 2789, 2791,
272 2797, 2801, 2803, 2819, 2833, 2837, 2843, 2851,
273 2857, 2861, 2879, 2887, 2897, 2903, 2909, 2917,
274 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999,
275 3001, 3011, 3019, 3023, 3037, 3041, 3049, 3061,
276 3067, 3079, 3083, 3089, 3109, 3119, 3121, 3137,
277 3163, 3167, 3169, 3181, 3187, 3191, 3203, 3209,
278 3217, 3221, 3229, 3251, 3253, 3257, 3259, 3271,
279 3299, 3301, 3307, 3313, 3319, 3323, 3329, 3331,
280 3343, 3347, 3359, 3361, 3371, 3373, 3389, 3391,
281 3407, 3413, 3433, 3449, 3457, 3461, 3463, 3467,
282 3469, 3491, 3499, 3511, 3517, 3527, 3529, 3533,
283 3539, 3541, 3547, 3557, 3559, 3571, 3581, 3583,
284 3593, 3607, 3613, 3617, 3623, 3631, 3637, 3643,
285 3659, 3671, 3673, 3677, 3691, 3697, 3701, 3709,
286 3719, 3727, 3733, 3739, 3761, 3767, 3769, 3779,
287 3793, 3797, 3803, 3821, 3823, 3833, 3847, 3851,
288 3853, 3863, 3877, 3881, 3889, 3907, 3911, 3917,
289 3919, 3923, 3929, 3931, 3943, 3947, 3967, 3989,
290 4001, 4003, 4007, 4013, 4019, 4021, 4027, 4049,
291 4051, 4057, 4073, 4079, 4091, 4093, 4099, 4111,
292 4127, 4129, 4133, 4139, 4153, 4157, 4159, 4177,
293 4201, 4211, 4217, 4219, 4229, 4231, 4241, 4243,
294 4253, 4259, 4261, 4271, 4273, 4283, 4289, 4297,
295 4327, 4337, 4339, 4349, 4357, 4363, 4373, 4391,
296 4397, 4409, 4421, 4423, 4441, 4447, 4451, 4457,
297 4463, 4481, 4483, 4493, 4507, 4513, 4517, 4519,
298 4523, 4547, 4549, 4561, 4567, 4583, 4591, 4597,
299 4603, 4621, 4637, 4639, 4643, 4649, 4651, 4657,
300 4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729,
301 4733, 4751, 4759, 4783, 4787, 4789, 4793, 4799,
302 4801, 4813, 4817, 4831, 4861, 4871, 4877, 4889,
303 4903, 4909, 4919, 4931, 4933, 4937, 4943, 4951,
304 4957, 4967, 4969, 4973, 4987, 4993, 4999,
305 0
306 };
307#define DIM(v) (sizeof(v)/sizeof((v)[0]))
308 static int no_of_small_prime_numbers = DIM (small_prime_numbers) - 1;
309
310 gcry_mpi_t prime, pminus1, val_2, val_3, result;
311 unsigned int i;
312 unsigned int step;
313 unsigned int mods[no_of_small_prime_numbers];
314 gcry_mpi_t tmp;
315 gcry_mpi_t sp;
316
317 GNUNET_assert (nbits >= 16);
318
319 /* Make nbits fit into mpz_t implementation. */
320 val_2 = gcry_mpi_set_ui (NULL, 2);
321 val_3 = gcry_mpi_set_ui (NULL, 3);
322 prime = gcry_mpi_snew (0);
323 result = gcry_mpi_new (0);
324 pminus1 = gcry_mpi_new (0);
325 *ptest = gcry_mpi_new (0);
326 tmp = gcry_mpi_new (0);
327 sp = gcry_mpi_new (0);
328 while (1)
329 {
330 /* generate a random number */
331 mpz_randomize (prime, nbits, hc);
332 /* Set high order bit to 1, set low order bit to 1. If we are
333 * generating a secret prime we are most probably doing that
334 * for RSA, to make sure that the modulus does have the
335 * requested key size we set the 2 high order bits. */
336 gcry_mpi_set_bit (prime, nbits - 1);
337 gcry_mpi_set_bit (prime, nbits - 2);
338 gcry_mpi_set_bit (prime, 0);
339
340 /* Calculate all remainders. */
341 for (i = 0; i < no_of_small_prime_numbers; i++)
342 {
343 size_t written;
344
345 gcry_mpi_set_ui (sp, small_prime_numbers[i]);
346 gcry_mpi_div (NULL, tmp, prime, sp, -1);
347 mods[i] = 0;
348 written = sizeof (unsigned int);
349 GNUNET_assert (0 ==
350 gcry_mpi_print (GCRYMPI_FMT_USG,
351 (unsigned char *) &mods[i], written,
352 &written, tmp));
353 adjust ((unsigned char *) &mods[i], written, sizeof (unsigned int));
354 mods[i] = ntohl (mods[i]);
355 }
356 /* Now try some primes starting with prime. */
357 for (step = 0; step < 20000; step += 2)
358 {
359 /* Check against all the small primes we have in mods. */
360 for (i = 0; i < no_of_small_prime_numbers; i++)
361 {
362 uint16_t x = small_prime_numbers[i];
363
364 while (mods[i] + step >= x)
365 mods[i] -= x;
366 if (!(mods[i] + step))
367 break;
368 }
369 if (i < no_of_small_prime_numbers)
370 continue; /* Found a multiple of an already known prime. */
371
372 gcry_mpi_add_ui (*ptest, prime, step);
373 if (!gcry_mpi_test_bit (*ptest, nbits - 2))
374 break;
375
376 /* Do a fast Fermat test now. */
377 gcry_mpi_sub_ui (pminus1, *ptest, 1);
378 gcry_mpi_powm (result, val_2, pminus1, *ptest);
379 if ((!gcry_mpi_cmp_ui (result, 1)) && (is_prime (*ptest, 5, hc)))
380 {
381 /* Got it. */
382 gcry_mpi_release (sp);
383 gcry_mpi_release (tmp);
384 gcry_mpi_release (val_2);
385 gcry_mpi_release (val_3);
386 gcry_mpi_release (result);
387 gcry_mpi_release (pminus1);
388 gcry_mpi_release (prime);
389 return;
390 }
391 }
392 }
393}
394
395/**
396 * Generate a key pair with a key of size NBITS.
397 * @param sk where to store the key
398 * @param nbits the number of bits to use
399 * @param hc the HC to use for PRNG (modified!)
400 */
401static void
402generate_kblock_key (KBlock_secret_key *sk, unsigned int nbits,
403 struct GNUNET_HashCode * hc)
404{
405 gcry_mpi_t t1, t2;
406 gcry_mpi_t phi; /* helper: (p-1)(q-1) */
407 gcry_mpi_t g;
408 gcry_mpi_t f;
409
410 /* make sure that nbits is even so that we generate p, q of equal size */
411 if ((nbits & 1))
412 nbits++;
413
414 sk->e = gcry_mpi_set_ui (NULL, 257);
415 sk->n = gcry_mpi_new (0);
416 sk->p = gcry_mpi_new (0);
417 sk->q = gcry_mpi_new (0);
418 sk->d = gcry_mpi_new (0);
419 sk->u = gcry_mpi_new (0);
420
421 t1 = gcry_mpi_new (0);
422 t2 = gcry_mpi_new (0);
423 phi = gcry_mpi_new (0);
424 g = gcry_mpi_new (0);
425 f = gcry_mpi_new (0);
426
427 do
428 {
429 do
430 {
431 gcry_mpi_release (sk->p);
432 gcry_mpi_release (sk->q);
433 gen_prime (&sk->p, nbits / 2, hc);
434 gen_prime (&sk->q, nbits / 2, hc);
435
436 if (gcry_mpi_cmp (sk->p, sk->q) > 0) /* p shall be smaller than q (for calc of u) */
437 gcry_mpi_swap (sk->p, sk->q);
438 /* calculate the modulus */
439 gcry_mpi_mul (sk->n, sk->p, sk->q);
440 }
441 while (gcry_mpi_get_nbits (sk->n) != nbits);
442
443 /* calculate Euler totient: phi = (p-1)(q-1) */
444 gcry_mpi_sub_ui (t1, sk->p, 1);
445 gcry_mpi_sub_ui (t2, sk->q, 1);
446 gcry_mpi_mul (phi, t1, t2);
447 gcry_mpi_gcd (g, t1, t2);
448 gcry_mpi_div (f, NULL, phi, g, 0);
449 while (0 == gcry_mpi_gcd (t1, sk->e, phi))
450 { /* (while gcd is not 1) */
451 gcry_mpi_add_ui (sk->e, sk->e, 2);
452 }
453
454 /* calculate the secret key d = e^1 mod phi */
455 }
456 while ((0 == gcry_mpi_invm (sk->d, sk->e, f)) ||
457 (0 == gcry_mpi_invm (sk->u, sk->p, sk->q)));
458
459 gcry_mpi_release (t1);
460 gcry_mpi_release (t2);
461 gcry_mpi_release (phi);
462 gcry_mpi_release (f);
463 gcry_mpi_release (g);
464}
465
466GNUNET_NETWORK_STRUCT_BEGIN
467
468/**
469 * Internal representation of the private key.
470 */
471struct KskRsaPrivateKeyBinaryEncoded
472{
473 /**
474 * Total size of the structure, in bytes, in big-endian!
475 */
476 uint16_t len GNUNET_PACKED;
477 uint16_t sizen GNUNET_PACKED; /* in big-endian! */
478 uint16_t sizee GNUNET_PACKED; /* in big-endian! */
479 uint16_t sized GNUNET_PACKED; /* in big-endian! */
480 uint16_t sizep GNUNET_PACKED; /* in big-endian! */
481 uint16_t sizeq GNUNET_PACKED; /* in big-endian! */
482 uint16_t sizedmp1 GNUNET_PACKED; /* in big-endian! */
483 uint16_t sizedmq1 GNUNET_PACKED; /* in big-endian! */
484 /* followed by the actual values */
485};
486GNUNET_NETWORK_STRUCT_END
487
488/**
489 * Deterministically (!) create a hostkey using only the
490 * given HashCode as input to the PRNG.
491 */
492static struct KskRsaPrivateKeyBinaryEncoded *
493makeKblockKeyInternal (const struct GNUNET_HashCode * hc)
494{
495 KBlock_secret_key sk;
496 struct GNUNET_HashCode hx;
497 unsigned char *pbu[6];
498 gcry_mpi_t *pkv[6];
499 size_t sizes[6];
500 struct KskRsaPrivateKeyBinaryEncoded *retval;
501 int i;
502 size_t size;
503
504 hx = *hc;
505 generate_kblock_key (&sk, 1024, /* at least 10x as fast than 2048 bits
506 * -- we simply cannot afford 2048 bits
507 * even on modern hardware, and especially
508 * not since clearly a dictionary attack
509 * will still be much cheaper
510 * than breaking a 1024 bit RSA key.
511 * If an adversary can spend the time to
512 * break a 1024 bit RSA key just to forge
513 * a signature -- SO BE IT. [ CG, 6/2005 ] */
514 &hx);
515 pkv[0] = &sk.n;
516 pkv[1] = &sk.e;
517 pkv[2] = &sk.d;
518 pkv[3] = &sk.p;
519 pkv[4] = &sk.q;
520 pkv[5] = &sk.u;
521 size = sizeof (struct KskRsaPrivateKeyBinaryEncoded);
522 for (i = 0; i < 6; i++)
523 {
524 gcry_mpi_aprint (GCRYMPI_FMT_STD, &pbu[i], &sizes[i], *pkv[i]);
525 size += sizes[i];
526 }
527 GNUNET_assert (size < 65536);
528 retval = GNUNET_malloc (size);
529 retval->len = htons (size);
530 i = 0;
531 retval->sizen = htons (sizes[0]);
532 memcpy (&((char *) &retval[1])[i], pbu[0], sizes[0]);
533 i += sizes[0];
534 retval->sizee = htons (sizes[1]);
535 memcpy (&((char *) &retval[1])[i], pbu[1], sizes[1]);
536 i += sizes[1];
537 retval->sized = htons (sizes[2]);
538 memcpy (&((char *) &retval[1])[i], pbu[2], sizes[2]);
539 i += sizes[2];
540 /* swap p and q! */
541 retval->sizep = htons (sizes[4]);
542 memcpy (&((char *) &retval[1])[i], pbu[4], sizes[4]);
543 i += sizes[4];
544 retval->sizeq = htons (sizes[3]);
545 memcpy (&((char *) &retval[1])[i], pbu[3], sizes[3]);
546 i += sizes[3];
547 retval->sizedmp1 = htons (0);
548 retval->sizedmq1 = htons (0);
549 memcpy (&((char *) &retval[1])[i], pbu[5], sizes[5]);
550 for (i = 0; i < 6; i++)
551 {
552 gcry_mpi_release (*pkv[i]);
553 free (pbu[i]);
554 }
555 return retval;
556}
557
558
559/**
560 * Entry in the KSK cache.
561 */
562struct KBlockKeyCacheLine
563{
564 /**
565 * Hash from which the key was generated.
566 */
567 struct GNUNET_HashCode hc;
568
569 /**
570 * The encoded key.
571 */
572 struct KskRsaPrivateKeyBinaryEncoded *pke;
573};
574
575
576/**
577 * Cached KSK keys so that we don't have to recompute them
578 * all the time.
579 */
580static struct KBlockKeyCacheLine **cache;
581
582
583/**
584 * Size of the 'cache' array.
585 */
586static unsigned int cacheSize;
587
588
589/**
590 * Deterministically (!) create a hostkey using only the
591 * given HashCode as input to the PRNG.
592 *
593 * @param hc hash code to generate the key from
594 * @return corresponding private key; must not be freed!
595 */
596struct GNUNET_CRYPTO_RsaPrivateKey *
597GNUNET_CRYPTO_rsa_key_create_from_hash (const struct GNUNET_HashCode * hc)
598{
599 struct KBlockKeyCacheLine *line;
600 unsigned int i;
601
602 for (i = 0; i < cacheSize; i++)
603 if (0 == memcmp (hc, &cache[i]->hc, sizeof (struct GNUNET_HashCode)))
604 return GNUNET_CRYPTO_rsa_decode_key ((const char*) cache[i]->pke,
605 ntohs (cache[i]->pke->len));
606 line = GNUNET_malloc (sizeof (struct KBlockKeyCacheLine));
607 line->hc = *hc;
608 line->pke = makeKblockKeyInternal (hc);
609 GNUNET_array_grow (cache, cacheSize, cacheSize + 1);
610 cache[cacheSize - 1] = line;
611 return GNUNET_CRYPTO_rsa_decode_key ((const char*) line->pke,
612 ntohs (line->pke->len));
613}
614
615
616/**
617 * Destructor that frees the KSK cache.
618 */
619void __attribute__ ((destructor)) GNUNET_CRYPTO_ksk_fini ()
620{
621 unsigned int i;
622
623 for (i = 0; i < cacheSize; i++)
624 {
625 GNUNET_free (cache[i]->pke);
626 GNUNET_free (cache[i]);
627 }
628 GNUNET_array_grow (cache, cacheSize, 0);
629}
630
631
632/* end of crypto_ksk.c */
diff --git a/src/util/crypto_rsa.c b/src/util/crypto_rsa.c
deleted file mode 100644
index 9d4dc91ce..000000000
--- a/src/util/crypto_rsa.c
+++ /dev/null
@@ -1,1386 +0,0 @@
1/*
2 This file is part of GNUnet.
3 (C) 2001, 2002, 2003, 2004, 2005, 2006, 2009 Christian Grothoff (and other contributing authors)
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 2, 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., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file util/crypto_rsa.c
23 * @brief public key cryptography (RSA) with libgcrypt
24 * @author Christian Grothoff
25 */
26#include "platform.h"
27#include <gcrypt.h>
28#include "gnunet_common.h"
29#include "gnunet_util_lib.h"
30
31#define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__)
32
33#define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "util", syscall)
34
35#define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename)
36
37#define HOSTKEY_LEN 2048
38
39#define EXTRA_CHECKS ALLOW_EXTRA_CHECKS
40
41
42/**
43 * The private information of an RSA key pair.
44 * NOTE: this must match the definition in crypto_ksk.c and gnunet-rsa.c!
45 */
46struct GNUNET_CRYPTO_RsaPrivateKey
47{
48 /**
49 * Libgcrypt S-expression for the ECC key.
50 */
51 gcry_sexp_t sexp;
52};
53
54/**
55 * Log an error message at log-level 'level' that indicates
56 * a failure of the command 'cmd' with the message given
57 * by gcry_strerror(rc).
58 */
59#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);
60
61/**
62 * If target != size, move target bytes to the
63 * end of the size-sized buffer and zero out the
64 * first target-size bytes.
65 *
66 * @param buf original buffer
67 * @param size number of bytes in the buffer
68 * @param target target size of the buffer
69 */
70static void
71adjust (unsigned char *buf, size_t size, size_t target)
72{
73 if (size < target)
74 {
75 memmove (&buf[target - size], buf, size);
76 memset (buf, 0, target - size);
77 }
78}
79
80
81/**
82 * Free memory occupied by RSA private key.
83 *
84 * @param key pointer to the memory to free
85 */
86void
87GNUNET_CRYPTO_rsa_key_free (struct GNUNET_CRYPTO_RsaPrivateKey *key)
88{
89 gcry_sexp_release (key->sexp);
90 GNUNET_free (key);
91}
92
93
94/**
95 * Extract values from an S-expression.
96 *
97 * @param array where to store the result(s)
98 * @param sexp S-expression to parse
99 * @param topname top-level name in the S-expression that is of interest
100 * @param elems names of the elements to extract
101 * @return 0 on success
102 */
103static int
104key_from_sexp (gcry_mpi_t * array, gcry_sexp_t sexp, const char *topname,
105 const char *elems)
106{
107 gcry_sexp_t list;
108 gcry_sexp_t l2;
109 const char *s;
110 unsigned int i;
111 unsigned int idx;
112
113 if (! (list = gcry_sexp_find_token (sexp, topname, 0)))
114 return 1;
115 l2 = gcry_sexp_cadr (list);
116 gcry_sexp_release (list);
117 list = l2;
118 if (! list)
119 return 2;
120 idx = 0;
121 for (s = elems; *s; s++, idx++)
122 {
123 if (! (l2 = gcry_sexp_find_token (list, s, 1)))
124 {
125 for (i = 0; i < idx; i++)
126 {
127 gcry_free (array[i]);
128 array[i] = NULL;
129 }
130 gcry_sexp_release (list);
131 return 3; /* required parameter not found */
132 }
133 array[idx] = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
134 gcry_sexp_release (l2);
135 if (! array[idx])
136 {
137 for (i = 0; i < idx; i++)
138 {
139 gcry_free (array[i]);
140 array[i] = NULL;
141 }
142 gcry_sexp_release (list);
143 return 4; /* required parameter is invalid */
144 }
145 }
146 gcry_sexp_release (list);
147 return 0;
148}
149
150
151/**
152 * Extract the public key of the host.
153 *
154 * @param priv the private key
155 * @param pub where to write the public key
156 */
157void
158GNUNET_CRYPTO_rsa_key_get_public (const struct GNUNET_CRYPTO_RsaPrivateKey
159 *priv,
160 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded
161 *pub)
162{
163 gcry_mpi_t skey[2];
164 size_t size;
165 int rc;
166
167 rc = key_from_sexp (skey, priv->sexp, "public-key", "ne");
168 if (0 != rc)
169 rc = key_from_sexp (skey, priv->sexp, "private-key", "ne");
170 if (0 != rc)
171 rc = key_from_sexp (skey, priv->sexp, "rsa", "ne");
172 GNUNET_assert (0 == rc);
173 pub->len =
174 htons (sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded) -
175 sizeof (pub->padding));
176 pub->sizen = htons (GNUNET_CRYPTO_RSA_DATA_ENCODING_LENGTH);
177 pub->padding = 0;
178 size = GNUNET_CRYPTO_RSA_DATA_ENCODING_LENGTH;
179 GNUNET_assert (0 ==
180 gcry_mpi_print (GCRYMPI_FMT_USG, &pub->key[0], size, &size,
181 skey[0]));
182 adjust (&pub->key[0], size, GNUNET_CRYPTO_RSA_DATA_ENCODING_LENGTH);
183 size = GNUNET_CRYPTO_RSA_KEY_LENGTH - GNUNET_CRYPTO_RSA_DATA_ENCODING_LENGTH;
184 GNUNET_assert (0 ==
185 gcry_mpi_print (GCRYMPI_FMT_USG,
186 &pub->key
187 [GNUNET_CRYPTO_RSA_DATA_ENCODING_LENGTH], size,
188 &size, skey[1]));
189 adjust (&pub->key[GNUNET_CRYPTO_RSA_DATA_ENCODING_LENGTH], size,
190 GNUNET_CRYPTO_RSA_KEY_LENGTH -
191 GNUNET_CRYPTO_RSA_DATA_ENCODING_LENGTH);
192 gcry_mpi_release (skey[0]);
193 gcry_mpi_release (skey[1]);
194}
195
196
197/**
198 * Get hash of the public key that corresponds to a private key.
199 *
200 * @param key RSA private key
201 * @param id buffer for hash of the public key
202 */
203void
204GNUNET_CRYPTO_rsa_get_public_key_hash (struct GNUNET_CRYPTO_RsaPrivateKey *key,
205 struct GNUNET_HashCode *id)
206{
207 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pk;
208 GNUNET_CRYPTO_rsa_key_get_public (key, &pk);
209 GNUNET_CRYPTO_hash (&pk, sizeof (pk), id);
210}
211
212
213/**
214 * Convert a public key to a string.
215 *
216 * @param pub key to convert
217 * @return string representing 'pub'
218 */
219char *
220GNUNET_CRYPTO_rsa_public_key_to_string (const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *pub)
221{
222 char *pubkeybuf;
223 size_t keylen = (sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded)) * 8;
224 char *end;
225
226 if (keylen % 5 > 0)
227 keylen += 5 - keylen % 5;
228 keylen /= 5;
229 pubkeybuf = GNUNET_malloc (keylen + 1);
230 end = GNUNET_STRINGS_data_to_string ((unsigned char *) pub,
231 sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
232 pubkeybuf,
233 keylen);
234 if (NULL == end)
235 {
236 GNUNET_free (pubkeybuf);
237 return NULL;
238 }
239 *end = '\0';
240 return pubkeybuf;
241}
242
243
244/**
245 * Convert a string representing a public key to a public key.
246 *
247 * @param enc encoded public key
248 * @param enclen number of bytes in enc (without 0-terminator)
249 * @param pub where to store the public key
250 * @return GNUNET_OK on success
251 */
252int
253GNUNET_CRYPTO_rsa_public_key_from_string (const char *enc,
254 size_t enclen,
255 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *pub)
256{
257 size_t keylen = (sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded)) * 8;
258
259 if (keylen % 5 > 0)
260 keylen += 5 - keylen % 5;
261 keylen /= 5;
262 if (enclen != keylen)
263 return GNUNET_SYSERR;
264
265 if (GNUNET_OK != GNUNET_STRINGS_string_to_data (enc, enclen,
266 (unsigned char*) pub,
267 sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded)))
268 return GNUNET_SYSERR;
269 if ( (ntohs (pub->len) != sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded)) ||
270 (ntohs (pub->padding) != 0) ||
271 (ntohs (pub->sizen) != GNUNET_CRYPTO_RSA_DATA_ENCODING_LENGTH) )
272 return GNUNET_SYSERR;
273 return GNUNET_OK;
274}
275
276
277/**
278 * Convert the given public key from the network format to the
279 * S-expression that can be used by libgcrypt.
280 *
281 * @param publicKey public key to decode
282 * @return NULL on error
283 */
284static gcry_sexp_t
285decode_public_key (const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *publicKey)
286{
287 gcry_sexp_t result;
288 gcry_mpi_t n;
289 gcry_mpi_t e;
290 size_t size;
291 size_t erroff;
292 int rc;
293
294 if ((ntohs (publicKey->sizen) != GNUNET_CRYPTO_RSA_DATA_ENCODING_LENGTH) ||
295 (ntohs (publicKey->len) !=
296 sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded) -
297 sizeof (publicKey->padding)))
298 {
299 GNUNET_break (0);
300 return NULL;
301 }
302 size = GNUNET_CRYPTO_RSA_DATA_ENCODING_LENGTH;
303 if (0 != (rc = gcry_mpi_scan (&n, GCRYMPI_FMT_USG, &publicKey->key[0], size, &size)))
304 {
305 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc);
306 return NULL;
307 }
308 size = GNUNET_CRYPTO_RSA_KEY_LENGTH - GNUNET_CRYPTO_RSA_DATA_ENCODING_LENGTH;
309 if (0 != (rc = gcry_mpi_scan (&e, GCRYMPI_FMT_USG,
310 &publicKey->key[GNUNET_CRYPTO_RSA_DATA_ENCODING_LENGTH],
311 size, &size)))
312 {
313 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc);
314 gcry_mpi_release (n);
315 return NULL;
316 }
317 rc = gcry_sexp_build (&result, &erroff, "(public-key(rsa(n %m)(e %m)))", n,
318 e);
319 gcry_mpi_release (n);
320 gcry_mpi_release (e);
321 if (0 != rc)
322 {
323 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc); /* erroff gives more info */
324 return NULL;
325 }
326 return result;
327}
328
329
330/**
331 * Encode the private key in a format suitable for
332 * storing it into a file.
333 *
334 * @return encoding of the private key.
335 * The first 4 bytes give the size of the array, as usual.
336 */
337struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded *
338GNUNET_CRYPTO_rsa_encode_key (const struct GNUNET_CRYPTO_RsaPrivateKey *hostkey)
339{
340 struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded *retval;
341 gcry_mpi_t pkv[6];
342 void *pbu[6];
343 size_t sizes[6];
344 int rc;
345 int i;
346 int size;
347
348#if EXTRA_CHECKS
349 if (gcry_pk_testkey (hostkey->sexp))
350 {
351 GNUNET_break (0);
352 return NULL;
353 }
354#endif
355
356 memset (pkv, 0, sizeof (gcry_mpi_t) * 6);
357 rc = key_from_sexp (pkv, hostkey->sexp, "private-key", "nedpqu");
358 if (rc)
359 rc = key_from_sexp (pkv, hostkey->sexp, "rsa", "nedpqu");
360 if (rc)
361 rc = key_from_sexp (pkv, hostkey->sexp, "private-key", "nedpq");
362 if (rc)
363 rc = key_from_sexp (pkv, hostkey->sexp, "rsa", "nedpq");
364 if (rc)
365 rc = key_from_sexp (pkv, hostkey->sexp, "private-key", "ned");
366 if (rc)
367 rc = key_from_sexp (pkv, hostkey->sexp, "rsa", "ned");
368 GNUNET_assert (0 == rc);
369 size = sizeof (struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded);
370 for (i = 0; i < 6; i++)
371 {
372 if (NULL != pkv[i])
373 {
374 GNUNET_assert (0 ==
375 gcry_mpi_aprint (GCRYMPI_FMT_USG,
376 (unsigned char **) &pbu[i], &sizes[i],
377 pkv[i]));
378 size += sizes[i];
379 }
380 else
381 {
382 pbu[i] = NULL;
383 sizes[i] = 0;
384 }
385 }
386 GNUNET_assert (size < 65536);
387 retval = GNUNET_malloc (size);
388 retval->len = htons (size);
389 i = 0;
390 retval->sizen = htons (sizes[0]);
391 memcpy (&((char *) (&retval[1]))[i], pbu[0], sizes[0]);
392 i += sizes[0];
393 retval->sizee = htons (sizes[1]);
394 memcpy (&((char *) (&retval[1]))[i], pbu[1], sizes[1]);
395 i += sizes[1];
396 retval->sized = htons (sizes[2]);
397 memcpy (&((char *) (&retval[1]))[i], pbu[2], sizes[2]);
398 i += sizes[2];
399 /* swap p and q! */
400 retval->sizep = htons (sizes[4]);
401 memcpy (&((char *) (&retval[1]))[i], pbu[4], sizes[4]);
402 i += sizes[4];
403 retval->sizeq = htons (sizes[3]);
404 memcpy (&((char *) (&retval[1]))[i], pbu[3], sizes[3]);
405 i += sizes[3];
406 retval->sizedmp1 = htons (0);
407 retval->sizedmq1 = htons (0);
408 memcpy (&((char *) (&retval[1]))[i], pbu[5], sizes[5]);
409 for (i = 0; i < 6; i++)
410 {
411 if (pkv[i] != NULL)
412 gcry_mpi_release (pkv[i]);
413 if (pbu[i] != NULL)
414 free (pbu[i]);
415 }
416 return retval;
417}
418
419
420/**
421 * Decode the private key from the file-format back
422 * to the "normal", internal format.
423 *
424 * @param buf the buffer where the private key data is stored
425 * @param len the length of the data in 'buffer'
426 * @return NULL on error
427 */
428struct GNUNET_CRYPTO_RsaPrivateKey *
429GNUNET_CRYPTO_rsa_decode_key (const char *buf, uint16_t len)
430{
431 struct GNUNET_CRYPTO_RsaPrivateKey *ret;
432 const struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded *encoding =
433 (const struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded *) buf;
434 gcry_sexp_t res;
435 gcry_mpi_t n;
436 gcry_mpi_t e;
437 gcry_mpi_t d;
438 gcry_mpi_t p;
439 gcry_mpi_t q;
440 gcry_mpi_t u;
441 int rc;
442 size_t size;
443 size_t pos;
444 uint16_t enc_len;
445 size_t erroff;
446
447 enc_len = ntohs (encoding->len);
448 if (len != enc_len)
449 return NULL;
450
451 pos = 0;
452 size = ntohs (encoding->sizen);
453 rc = gcry_mpi_scan (&n, GCRYMPI_FMT_USG,
454 &((const unsigned char *) (&encoding[1]))[pos], size,
455 &size);
456 pos += ntohs (encoding->sizen);
457 if (0 != rc)
458 {
459 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc);
460 return NULL;
461 }
462 size = ntohs (encoding->sizee);
463 rc = gcry_mpi_scan (&e, GCRYMPI_FMT_USG,
464 &((const unsigned char *) (&encoding[1]))[pos], size,
465 &size);
466 pos += ntohs (encoding->sizee);
467 if (0 != rc)
468 {
469 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc);
470 gcry_mpi_release (n);
471 return NULL;
472 }
473 size = ntohs (encoding->sized);
474 rc = gcry_mpi_scan (&d, GCRYMPI_FMT_USG,
475 &((const unsigned char *) (&encoding[1]))[pos], size,
476 &size);
477 pos += ntohs (encoding->sized);
478 if (0 != rc)
479 {
480 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc);
481 gcry_mpi_release (n);
482 gcry_mpi_release (e);
483 return NULL;
484 }
485 /* swap p and q! */
486 size = ntohs (encoding->sizep);
487 if (size > 0)
488 {
489 rc = gcry_mpi_scan (&q, GCRYMPI_FMT_USG,
490 &((const unsigned char *) (&encoding[1]))[pos], size,
491 &size);
492 pos += ntohs (encoding->sizep);
493 if (0 != rc)
494 {
495 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc);
496 gcry_mpi_release (n);
497 gcry_mpi_release (e);
498 gcry_mpi_release (d);
499 return NULL;
500 }
501 }
502 else
503 q = NULL;
504 size = ntohs (encoding->sizeq);
505 if (size > 0)
506 {
507 rc = gcry_mpi_scan (&p, GCRYMPI_FMT_USG,
508 &((const unsigned char *) (&encoding[1]))[pos], size,
509 &size);
510 pos += ntohs (encoding->sizeq);
511 if (0 != rc)
512 {
513 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc);
514 gcry_mpi_release (n);
515 gcry_mpi_release (e);
516 gcry_mpi_release (d);
517 if (NULL != q)
518 gcry_mpi_release (q);
519 return NULL;
520 }
521 }
522 else
523 p = NULL;
524 pos += ntohs (encoding->sizedmp1);
525 pos += ntohs (encoding->sizedmq1);
526 size =
527 ntohs (encoding->len) - sizeof (struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded) - pos;
528 if (size > 0)
529 {
530 rc = gcry_mpi_scan (&u, GCRYMPI_FMT_USG,
531 &((const unsigned char *) (&encoding[1]))[pos], size,
532 &size);
533 if (0 != rc)
534 {
535 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc);
536 gcry_mpi_release (n);
537 gcry_mpi_release (e);
538 gcry_mpi_release (d);
539 if (NULL != p)
540 gcry_mpi_release (p);
541 if (NULL != q)
542 gcry_mpi_release (q);
543 return NULL;
544 }
545 }
546 else
547 u = NULL;
548
549 if ((NULL != p) && (NULL != q) && (NULL != u))
550 {
551 rc = gcry_sexp_build (&res, &erroff,
552 "(private-key(rsa(n %m)(e %m)(d %m)(p %m)(q %m)(u %m)))",
553 n, e, d, p, q, u);
554 }
555 else
556 {
557 if ((NULL != p) && (NULL != q))
558 {
559 rc = gcry_sexp_build (&res, &erroff,
560 "(private-key(rsa(n %m)(e %m)(d %m)(p %m)(q %m)))",
561 n, e, d, p, q);
562 }
563 else
564 {
565 rc = gcry_sexp_build (&res, &erroff,
566 "(private-key(rsa(n %m)(e %m)(d %m)))", n, e, d);
567 }
568 }
569 gcry_mpi_release (n);
570 gcry_mpi_release (e);
571 gcry_mpi_release (d);
572 if (NULL != p)
573 gcry_mpi_release (p);
574 if (NULL != q)
575 gcry_mpi_release (q);
576 if (NULL != u)
577 gcry_mpi_release (u);
578
579 if (0 != rc)
580 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
581#if EXTRA_CHECKS
582 if (0 != (rc = gcry_pk_testkey (res)))
583 {
584 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
585 return NULL;
586 }
587#endif
588 ret = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_RsaPrivateKey));
589 ret->sexp = res;
590 return ret;
591}
592
593
594/**
595 * Create a new private key. Caller must free return value.
596 *
597 * @return fresh private key
598 */
599static struct GNUNET_CRYPTO_RsaPrivateKey *
600rsa_key_create ()
601{
602 struct GNUNET_CRYPTO_RsaPrivateKey *ret;
603 gcry_sexp_t s_key;
604 gcry_sexp_t s_keyparam;
605
606 GNUNET_assert (0 ==
607 gcry_sexp_build (&s_keyparam, NULL,
608 "(genkey(rsa(nbits %d)(rsa-use-e 3:257)))",
609 HOSTKEY_LEN));
610 GNUNET_assert (0 == gcry_pk_genkey (&s_key, s_keyparam));
611 gcry_sexp_release (s_keyparam);
612#if EXTRA_CHECKS
613 GNUNET_assert (0 == gcry_pk_testkey (s_key));
614#endif
615 ret = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_RsaPrivateKey));
616 ret->sexp = s_key;
617 return ret;
618}
619
620
621/**
622 * Try to read the private key from the given file.
623 *
624 * @param filename file to read the key from
625 * @return NULL on error
626 */
627static struct GNUNET_CRYPTO_RsaPrivateKey *
628try_read_key (const char *filename)
629{
630 struct GNUNET_CRYPTO_RsaPrivateKey *ret;
631 struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded *enc;
632 struct GNUNET_DISK_FileHandle *fd;
633 OFF_T fs;
634 uint16_t len;
635
636 if (GNUNET_YES != GNUNET_DISK_file_test (filename))
637 return NULL;
638
639 /* hostkey file exists already, read it! */
640 if (NULL == (fd = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READ,
641 GNUNET_DISK_PERM_NONE)))
642 {
643 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "open", filename);
644 return NULL;
645 }
646 if (GNUNET_OK != (GNUNET_DISK_file_handle_size (fd, &fs)))
647 {
648 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "stat", filename);
649 (void) GNUNET_DISK_file_close (fd);
650 return NULL;
651 }
652 if (0 == fs)
653 {
654 GNUNET_break (GNUNET_OK == GNUNET_DISK_file_close (fd));
655 return NULL;
656 }
657 if (fs > UINT16_MAX)
658 {
659 LOG (GNUNET_ERROR_TYPE_ERROR,
660 _("File `%s' does not contain a valid private key (too long, %llu bytes). Renaming it.\n"),
661 filename,
662 (unsigned long long) fs);
663 GNUNET_break (GNUNET_OK == GNUNET_DISK_file_close (fd));
664 GNUNET_DISK_file_backup (filename);
665 return NULL;
666 }
667
668 enc = GNUNET_malloc (fs);
669 GNUNET_break (fs == GNUNET_DISK_file_read (fd, enc, fs));
670 len = ntohs (enc->len);
671 ret = NULL;
672 if ((len != fs) ||
673 (NULL == (ret = GNUNET_CRYPTO_rsa_decode_key ((char *) enc, len))))
674 {
675 LOG (GNUNET_ERROR_TYPE_ERROR,
676 _("File `%s' does not contain a valid private key (failed decode, %llu bytes). Deleting it.\n"),
677 filename,
678 (unsigned long long) fs);
679 GNUNET_break (GNUNET_OK == GNUNET_DISK_file_close (fd));
680 GNUNET_DISK_file_backup (filename);
681 GNUNET_free (enc);
682 return NULL;
683 }
684 GNUNET_free (enc);
685
686 GNUNET_break (GNUNET_OK == GNUNET_DISK_file_close (fd));
687 return ret;
688}
689
690
691/**
692 * Wait for a short time (we're trying to lock a file or want
693 * to give another process a shot at finishing a disk write, etc.).
694 * Sleeps for 100ms (as that should be long enough for virtually all
695 * modern systems to context switch and allow another process to do
696 * some 'real' work).
697 */
698static void
699short_wait ()
700{
701 struct GNUNET_TIME_Relative timeout;
702
703 timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 100);
704 (void) GNUNET_NETWORK_socket_select (NULL, NULL, NULL, timeout);
705}
706
707
708/**
709 * Open existing private key file and read it. If the
710 * file does not exist, or the contents of the file are
711 * invalid, the function fails
712 * Caller must free returned value.
713 *
714 * @return a private key, NULL on error (for example,
715 * permission denied) or when file does not exist or contains invalid
716 * data.
717 */
718struct GNUNET_CRYPTO_RsaPrivateKey *
719GNUNET_CRYPTO_rsa_key_create_from_existing_file (const char *filename)
720{
721 struct GNUNET_CRYPTO_RsaPrivateKey *ret;
722 struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded *enc;
723 uint16_t len;
724 struct GNUNET_DISK_FileHandle *fd;
725 unsigned int cnt;
726 int ec;
727 uint64_t fs;
728 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pub;
729 struct GNUNET_PeerIdentity pid;
730
731 fd = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READ,
732 GNUNET_DISK_PERM_NONE);
733 if (NULL == fd)
734 {
735 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "open", filename);
736 return NULL;
737 }
738 cnt = 0;
739 while (1)
740 {
741 if (GNUNET_YES !=
742 GNUNET_DISK_file_lock (fd, 0,
743 sizeof (struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded),
744 GNUNET_NO))
745 {
746 if (0 == ++cnt % 60)
747 {
748 ec = errno;
749 LOG (GNUNET_ERROR_TYPE_ERROR,
750 _("Could not acquire lock on file `%s': %s...\n"), filename,
751 STRERROR (ec));
752 LOG (GNUNET_ERROR_TYPE_ERROR,
753 _
754 ("This may be ok if someone is currently generating a private key.\n"));
755 }
756 short_wait ();
757 continue;
758 }
759 if (GNUNET_YES != GNUNET_DISK_file_test (filename))
760 {
761 /* eh, what!? File we opened is now gone!? */
762 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "stat", filename);
763 if (GNUNET_YES !=
764 GNUNET_DISK_file_unlock (fd, 0,
765 sizeof (struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded)))
766 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename);
767 GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_close (fd));
768
769 return NULL;
770 }
771 if (GNUNET_OK != GNUNET_DISK_file_size (filename, &fs, GNUNET_YES, GNUNET_YES))
772 fs = 0;
773 if (fs < sizeof (struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded))
774 {
775 /* maybe we got the read lock before the key generating
776 * process had a chance to get the write lock; give it up! */
777 if (GNUNET_YES !=
778 GNUNET_DISK_file_unlock (fd, 0,
779 sizeof (struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded)))
780 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename);
781 if (0 == ++cnt % 10)
782 {
783 LOG (GNUNET_ERROR_TYPE_ERROR,
784 _
785 ("When trying to read key file `%s' I found %u bytes but I need at least %u.\n"),
786 filename, (unsigned int) fs,
787 (unsigned int) sizeof (struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded));
788 LOG (GNUNET_ERROR_TYPE_ERROR,
789 _
790 ("This may be ok if someone is currently generating a private key.\n"));
791 }
792 short_wait (); /* wait a bit longer! */
793 continue;
794 }
795 break;
796 }
797 enc = GNUNET_malloc (fs);
798 GNUNET_assert (fs == GNUNET_DISK_file_read (fd, enc, fs));
799 len = ntohs (enc->len);
800 ret = NULL;
801 if ((len != fs) ||
802 (NULL == (ret = GNUNET_CRYPTO_rsa_decode_key ((char *) enc, len))))
803 {
804 LOG (GNUNET_ERROR_TYPE_ERROR,
805 _("File `%s' does not contain a valid private key. Deleting it.\n"),
806 filename);
807 GNUNET_DISK_file_backup (filename);
808 }
809 GNUNET_free (enc);
810 if (GNUNET_YES !=
811 GNUNET_DISK_file_unlock (fd, 0,
812 sizeof (struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded)))
813 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename);
814 GNUNET_assert (GNUNET_YES == GNUNET_DISK_file_close (fd));
815 if (ret != NULL)
816 {
817 GNUNET_CRYPTO_rsa_key_get_public (ret, &pub);
818 GNUNET_CRYPTO_hash (&pub, sizeof (pub), &pid.hashPubKey);
819 }
820 return ret;
821}
822
823/**
824 * Create a new private key by reading it from a file. If the
825 * files does not exist, create a new key and write it to the
826 * file. Caller must free return value. Note that this function
827 * can not guarantee that another process might not be trying
828 * the same operation on the same file at the same time.
829 * If the contents of the file
830 * are invalid the old file is deleted and a fresh key is
831 * created.
832 *
833 * @return new private key, NULL on error (for example,
834 * permission denied)
835 */
836struct GNUNET_CRYPTO_RsaPrivateKey *
837GNUNET_CRYPTO_rsa_key_create_from_file (const char *filename)
838{
839 struct GNUNET_CRYPTO_RsaPrivateKey *ret;
840 struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded *enc;
841 struct GNUNET_DISK_FileHandle *fd;
842 unsigned int cnt;
843 int ec;
844 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pub;
845 struct GNUNET_PeerIdentity pid;
846
847 if (GNUNET_SYSERR == GNUNET_DISK_directory_create_for_file (filename))
848 return NULL;
849
850 while (GNUNET_YES != GNUNET_DISK_file_test (filename))
851 {
852 fd = GNUNET_DISK_file_open (filename,
853 GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_CREATE
854 | GNUNET_DISK_OPEN_FAILIFEXISTS,
855 GNUNET_DISK_PERM_USER_READ |
856 GNUNET_DISK_PERM_USER_WRITE);
857 if (NULL == fd)
858 {
859 if (EEXIST == errno)
860 {
861 if (GNUNET_YES != GNUNET_DISK_file_test (filename))
862 {
863 /* must exist but not be accessible, fail for good! */
864 if (0 != ACCESS (filename, R_OK))
865 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "access", filename);
866 else
867 GNUNET_break (0); /* what is going on!? */
868 return NULL;
869 }
870 continue;
871 }
872 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "open", filename);
873 return NULL;
874 }
875 cnt = 0;
876
877 while (GNUNET_YES !=
878 GNUNET_DISK_file_lock (fd, 0,
879 sizeof (struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded),
880 GNUNET_YES))
881 {
882 short_wait ();
883 if (0 == ++cnt % 10)
884 {
885 ec = errno;
886 LOG (GNUNET_ERROR_TYPE_ERROR,
887 _("Could not acquire lock on file `%s': %s...\n"), filename,
888 STRERROR (ec));
889 }
890 }
891 LOG (GNUNET_ERROR_TYPE_INFO,
892 _("Creating a new private key. This may take a while.\n"));
893 ret = rsa_key_create ();
894 GNUNET_assert (ret != NULL);
895 enc = GNUNET_CRYPTO_rsa_encode_key (ret);
896 GNUNET_assert (enc != NULL);
897 GNUNET_assert (ntohs (enc->len) ==
898 GNUNET_DISK_file_write (fd, enc, ntohs (enc->len)));
899 GNUNET_free (enc);
900
901 GNUNET_DISK_file_sync (fd);
902 if (GNUNET_YES !=
903 GNUNET_DISK_file_unlock (fd, 0,
904 sizeof (struct GNUNET_CRYPTO_RsaPrivateKeyBinaryEncoded)))
905 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename);
906 GNUNET_assert (GNUNET_YES == GNUNET_DISK_file_close (fd));
907 GNUNET_CRYPTO_rsa_key_get_public (ret, &pub);
908 GNUNET_CRYPTO_hash (&pub, sizeof (pub), &pid.hashPubKey);
909 return ret;
910 }
911 /* hostkey file exists already, read it! */
912 return GNUNET_CRYPTO_rsa_key_create_from_existing_file (filename);
913}
914
915
916/**
917 * Handle to cancel private key generation and state for the
918 * key generation operation.
919 */
920struct GNUNET_CRYPTO_RsaKeyGenerationContext
921{
922
923 /**
924 * Continuation to call upon completion.
925 */
926 GNUNET_CRYPTO_RsaKeyCallback cont;
927
928 /**
929 * Closure for 'cont'.
930 */
931 void *cont_cls;
932
933 /**
934 * Name of the file.
935 */
936 char *filename;
937
938 /**
939 * Handle to the helper process which does the key generation.
940 */
941 struct GNUNET_OS_Process *gnunet_rsa;
942
943 /**
944 * Handle to 'stdout' of gnunet-rsa. We 'read' on stdout to detect
945 * process termination (instead of messing with SIGCHLD).
946 */
947 struct GNUNET_DISK_PipeHandle *gnunet_rsa_out;
948
949 /**
950 * Location where we store the private key if it already existed.
951 * (if this is used, 'filename', 'gnunet_rsa' and 'gnunet_rsa_out' will
952 * not be used).
953 */
954 struct GNUNET_CRYPTO_RsaPrivateKey *pk;
955
956 /**
957 * Task reading from 'gnunet_rsa_out' to wait for process termination.
958 */
959 GNUNET_SCHEDULER_TaskIdentifier read_task;
960
961};
962
963
964/**
965 * Task called upon shutdown or process termination of 'gnunet-rsa' during
966 * RSA key generation. Check where we are and perform the appropriate
967 * action.
968 *
969 * @param cls the 'struct GNUNET_CRYPTO_RsaKeyGenerationContext'
970 * @param tc scheduler context
971 */
972static void
973check_key_generation_completion (void *cls,
974 const struct GNUNET_SCHEDULER_TaskContext *tc)
975{
976 struct GNUNET_CRYPTO_RsaKeyGenerationContext *gc = cls;
977 struct GNUNET_CRYPTO_RsaPrivateKey *pk;
978
979 gc->read_task = GNUNET_SCHEDULER_NO_TASK;
980 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
981 {
982 gc->cont (gc->cont_cls, NULL, _("interrupted by shutdown"));
983 GNUNET_CRYPTO_rsa_key_create_stop (gc);
984 return;
985 }
986 GNUNET_assert (GNUNET_OK ==
987 GNUNET_OS_process_wait (gc->gnunet_rsa));
988 GNUNET_OS_process_destroy (gc->gnunet_rsa);
989 gc->gnunet_rsa = NULL;
990 if (NULL == (pk = try_read_key (gc->filename)))
991 {
992 GNUNET_break (0);
993 gc->cont (gc->cont_cls, NULL, _("gnunet-rsa failed"));
994 GNUNET_CRYPTO_rsa_key_create_stop (gc);
995 return;
996 }
997 gc->cont (gc->cont_cls, pk, NULL);
998 GNUNET_DISK_pipe_close (gc->gnunet_rsa_out);
999 GNUNET_free (gc->filename);
1000 GNUNET_free (gc);
1001}
1002
1003
1004/**
1005 * Return the private RSA key which already existed on disk
1006 * (asynchronously) to the caller.
1007 *
1008 * @param cls the 'struct GNUNET_CRYPTO_RsaKeyGenerationContext'
1009 * @param tc scheduler context (unused)
1010 */
1011static void
1012async_return_key (void *cls,
1013 const struct GNUNET_SCHEDULER_TaskContext *tc)
1014{
1015 struct GNUNET_CRYPTO_RsaKeyGenerationContext *gc = cls;
1016
1017 gc->cont (gc->cont_cls,
1018 gc->pk,
1019 NULL);
1020 GNUNET_free (gc);
1021}
1022
1023
1024/**
1025 * Create a new private key by reading it from a file. If the files
1026 * does not exist, create a new key and write it to the file. If the
1027 * contents of the file are invalid the old file is deleted and a
1028 * fresh key is created.
1029 *
1030 * @param filename name of file to use for storage
1031 * @param cont function to call when done (or on errors)
1032 * @param cont_cls closure for 'cont'
1033 * @return handle to abort operation, NULL on fatal errors (cont will not be called if NULL is returned)
1034 */
1035struct GNUNET_CRYPTO_RsaKeyGenerationContext *
1036GNUNET_CRYPTO_rsa_key_create_start (const char *filename,
1037 GNUNET_CRYPTO_RsaKeyCallback cont,
1038 void *cont_cls)
1039{
1040 struct GNUNET_CRYPTO_RsaKeyGenerationContext *gc;
1041 struct GNUNET_CRYPTO_RsaPrivateKey *pk;
1042
1043 if (NULL != (pk = try_read_key (filename)))
1044 {
1045 /* quick happy ending: key already exists! */
1046 gc = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_RsaKeyGenerationContext));
1047 gc->pk = pk;
1048 gc->cont = cont;
1049 gc->cont_cls = cont_cls;
1050 gc->read_task = GNUNET_SCHEDULER_add_now (&async_return_key,
1051 gc);
1052 return gc;
1053 }
1054 gc = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_RsaKeyGenerationContext));
1055 gc->filename = GNUNET_strdup (filename);
1056 gc->cont = cont;
1057 gc->cont_cls = cont_cls;
1058 gc->gnunet_rsa_out = GNUNET_DISK_pipe (GNUNET_NO,
1059 GNUNET_NO,
1060 GNUNET_NO,
1061 GNUNET_YES);
1062 if (NULL == gc->gnunet_rsa_out)
1063 {
1064 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "pipe");
1065 GNUNET_free (gc->filename);
1066 GNUNET_free (gc);
1067 return NULL;
1068 }
1069 gc->gnunet_rsa = GNUNET_OS_start_process (GNUNET_NO,
1070 GNUNET_OS_INHERIT_STD_ERR,
1071 NULL,
1072 gc->gnunet_rsa_out,
1073 "gnunet-rsa",
1074 "gnunet-rsa",
1075 gc->filename,
1076 NULL);
1077 if (NULL == gc->gnunet_rsa)
1078 {
1079 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "fork");
1080 GNUNET_DISK_pipe_close (gc->gnunet_rsa_out);
1081 GNUNET_free (gc->filename);
1082 GNUNET_free (gc);
1083 return NULL;
1084 }
1085 GNUNET_assert (GNUNET_OK ==
1086 GNUNET_DISK_pipe_close_end (gc->gnunet_rsa_out,
1087 GNUNET_DISK_PIPE_END_WRITE));
1088 gc->read_task = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
1089 GNUNET_DISK_pipe_handle (gc->gnunet_rsa_out,
1090 GNUNET_DISK_PIPE_END_READ),
1091 &check_key_generation_completion,
1092 gc);
1093 return gc;
1094}
1095
1096
1097/**
1098 * Abort RSA key generation.
1099 *
1100 * @param gc key generation context to abort
1101 */
1102void
1103GNUNET_CRYPTO_rsa_key_create_stop (struct GNUNET_CRYPTO_RsaKeyGenerationContext *gc)
1104{
1105 if (GNUNET_SCHEDULER_NO_TASK != gc->read_task)
1106 {
1107 GNUNET_SCHEDULER_cancel (gc->read_task);
1108 gc->read_task = GNUNET_SCHEDULER_NO_TASK;
1109 }
1110 if (NULL != gc->gnunet_rsa)
1111 {
1112 (void) GNUNET_OS_process_kill (gc->gnunet_rsa, SIGKILL);
1113 GNUNET_break (GNUNET_OK ==
1114 GNUNET_OS_process_wait (gc->gnunet_rsa));
1115 GNUNET_OS_process_destroy (gc->gnunet_rsa);
1116 GNUNET_DISK_pipe_close (gc->gnunet_rsa_out);
1117 }
1118
1119 if (NULL != gc->filename)
1120 {
1121 if (0 != UNLINK (gc->filename))
1122 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "unlink", gc->filename);
1123 GNUNET_free (gc->filename);
1124 }
1125 if (NULL != gc->pk)
1126 GNUNET_CRYPTO_rsa_key_free (gc->pk);
1127 GNUNET_free (gc);
1128}
1129
1130
1131/**
1132 * Setup a key file for a peer given the name of the
1133 * configuration file (!). This function is used so that
1134 * at a later point code can be certain that reading a
1135 * key is fast (for example in time-dependent testcases).
1136 *
1137 * @param cfg_name name of the configuration file to use
1138 */
1139void
1140GNUNET_CRYPTO_rsa_setup_hostkey (const char *cfg_name)
1141{
1142 struct GNUNET_CONFIGURATION_Handle *cfg;
1143 struct GNUNET_CRYPTO_RsaPrivateKey *pk;
1144 char *fn;
1145
1146 cfg = GNUNET_CONFIGURATION_create ();
1147 (void) GNUNET_CONFIGURATION_load (cfg, cfg_name);
1148 if (GNUNET_OK ==
1149 GNUNET_CONFIGURATION_get_value_filename (cfg, "GNUNETD", "HOSTKEY", &fn))
1150 {
1151 pk = GNUNET_CRYPTO_rsa_key_create_from_file (fn);
1152 if (NULL != pk)
1153 GNUNET_CRYPTO_rsa_key_free (pk);
1154 GNUNET_free (fn);
1155 }
1156 GNUNET_CONFIGURATION_destroy (cfg);
1157}
1158
1159
1160/**
1161 * Encrypt a block with the public key of another host that uses the
1162 * same cipher.
1163 *
1164 * @param block the block to encrypt
1165 * @param size the size of block
1166 * @param publicKey the encoded public key used to encrypt
1167 * @param target where to store the encrypted block
1168 * @returns GNUNET_SYSERR on error, GNUNET_OK if ok
1169 */
1170int
1171GNUNET_CRYPTO_rsa_encrypt (const void *block, size_t size,
1172 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded
1173 *publicKey,
1174 struct GNUNET_CRYPTO_RsaEncryptedData *target)
1175{
1176 gcry_sexp_t result;
1177 gcry_sexp_t data;
1178 gcry_sexp_t psexp;
1179 gcry_mpi_t val;
1180 gcry_mpi_t rval;
1181 size_t isize;
1182 size_t erroff;
1183
1184 GNUNET_assert (size <= sizeof (struct GNUNET_HashCode));
1185 if (! (psexp = decode_public_key (publicKey)))
1186 return GNUNET_SYSERR;
1187 isize = size;
1188 GNUNET_assert (0 ==
1189 gcry_mpi_scan (&val, GCRYMPI_FMT_USG, block, isize, &isize));
1190 GNUNET_assert (0 ==
1191 gcry_sexp_build (&data, &erroff,
1192 "(data (flags pkcs1)(value %m))", val));
1193 gcry_mpi_release (val);
1194 GNUNET_assert (0 == gcry_pk_encrypt (&result, data, psexp));
1195 gcry_sexp_release (data);
1196 gcry_sexp_release (psexp);
1197 GNUNET_assert (0 == key_from_sexp (&rval, result, "rsa", "a"));
1198 gcry_sexp_release (result);
1199 isize = sizeof (struct GNUNET_CRYPTO_RsaEncryptedData);
1200 GNUNET_assert (0 ==
1201 gcry_mpi_print (GCRYMPI_FMT_USG, (unsigned char *) target,
1202 isize, &isize, rval));
1203 gcry_mpi_release (rval);
1204 adjust (&target->encoding[0], isize,
1205 sizeof (struct GNUNET_CRYPTO_RsaEncryptedData));
1206 return GNUNET_OK;
1207}
1208
1209
1210/**
1211 * Decrypt a given block with the key.
1212 *
1213 * @param key the key with which to decrypt this block
1214 * @param block the data to decrypt, encoded as returned by encrypt
1215 * @param result pointer to a location where the result can be stored
1216 * @param max the maximum number of bits to store for the result, if
1217 * the decrypted block is bigger, an error is returned
1218 * @return the size of the decrypted block, -1 on error
1219 */
1220ssize_t
1221GNUNET_CRYPTO_rsa_decrypt (const struct GNUNET_CRYPTO_RsaPrivateKey * key,
1222 const struct GNUNET_CRYPTO_RsaEncryptedData * block,
1223 void *result, size_t max)
1224{
1225 gcry_sexp_t resultsexp;
1226 gcry_sexp_t data;
1227 size_t erroff;
1228 size_t size;
1229 gcry_mpi_t val;
1230 unsigned char *endp;
1231 unsigned char *tmp;
1232
1233#if EXTRA_CHECKS
1234 GNUNET_assert (0 == gcry_pk_testkey (key->sexp));
1235#endif
1236 size = sizeof (struct GNUNET_CRYPTO_RsaEncryptedData);
1237 GNUNET_assert (0 ==
1238 gcry_mpi_scan (&val, GCRYMPI_FMT_USG, &block->encoding[0],
1239 size, &size));
1240 GNUNET_assert (0 ==
1241 gcry_sexp_build (&data, &erroff, "(enc-val(flags)(rsa(a %m)))",
1242 val));
1243 gcry_mpi_release (val);
1244 GNUNET_assert (0 == gcry_pk_decrypt (&resultsexp, data, key->sexp));
1245 gcry_sexp_release (data);
1246 /* resultsexp has format "(value %m)" */
1247 GNUNET_assert (NULL !=
1248 (val = gcry_sexp_nth_mpi (resultsexp, 1, GCRYMPI_FMT_USG)));
1249 gcry_sexp_release (resultsexp);
1250 tmp = GNUNET_malloc (max + HOSTKEY_LEN / 8);
1251 size = max + HOSTKEY_LEN / 8;
1252 GNUNET_assert (0 == gcry_mpi_print (GCRYMPI_FMT_USG, tmp, size, &size, val));
1253 gcry_mpi_release (val);
1254 endp = tmp;
1255 endp += (size - max);
1256 size = max;
1257 memcpy (result, endp, size);
1258 GNUNET_free (tmp);
1259 return size;
1260}
1261
1262
1263/**
1264 * Convert the data specified in the given purpose argument to an
1265 * S-expression suitable for signature operations.
1266 *
1267 * @param purpose data to convert
1268 * @return converted s-expression
1269 */
1270static gcry_sexp_t
1271data_to_pkcs1 (const struct GNUNET_CRYPTO_RsaSignaturePurpose *purpose)
1272{
1273 struct GNUNET_HashCode hc;
1274 size_t bufSize;
1275 gcry_sexp_t data;
1276
1277 GNUNET_CRYPTO_hash (purpose, ntohl (purpose->size), &hc);
1278#define FORMATSTRING "(4:data(5:flags5:pkcs1)(4:hash6:sha51264:0123456789012345678901234567890123456789012345678901234567890123))"
1279 bufSize = strlen (FORMATSTRING) + 1;
1280 {
1281 char buff[bufSize];
1282
1283 memcpy (buff, FORMATSTRING, bufSize);
1284 memcpy (&buff
1285 [bufSize -
1286 strlen
1287 ("0123456789012345678901234567890123456789012345678901234567890123))")
1288 - 1], &hc, sizeof (struct GNUNET_HashCode));
1289 GNUNET_assert (0 == gcry_sexp_new (&data, buff, bufSize, 0));
1290 }
1291#undef FORMATSTRING
1292 return data;
1293}
1294
1295
1296/**
1297 * Sign a given block.
1298 *
1299 * @param key private key to use for the signing
1300 * @param purpose what to sign (size, purpose)
1301 * @param sig where to write the signature
1302 * @return GNUNET_SYSERR on error, GNUNET_OK on success
1303 */
1304int
1305GNUNET_CRYPTO_rsa_sign (const struct GNUNET_CRYPTO_RsaPrivateKey *key,
1306 const struct GNUNET_CRYPTO_RsaSignaturePurpose *purpose,
1307 struct GNUNET_CRYPTO_RsaSignature *sig)
1308{
1309 gcry_sexp_t result;
1310 gcry_sexp_t data;
1311 size_t ssize;
1312 gcry_mpi_t rval;
1313
1314 data = data_to_pkcs1 (purpose);
1315 GNUNET_assert (0 == gcry_pk_sign (&result, data, key->sexp));
1316 gcry_sexp_release (data);
1317 GNUNET_assert (0 == key_from_sexp (&rval, result, "rsa", "s"));
1318 gcry_sexp_release (result);
1319 ssize = sizeof (struct GNUNET_CRYPTO_RsaSignature);
1320 GNUNET_assert (0 ==
1321 gcry_mpi_print (GCRYMPI_FMT_USG, (unsigned char *) sig, ssize,
1322 &ssize, rval));
1323 gcry_mpi_release (rval);
1324 adjust (sig->sig, ssize, sizeof (struct GNUNET_CRYPTO_RsaSignature));
1325 return GNUNET_OK;
1326}
1327
1328
1329/**
1330 * Verify signature.
1331 *
1332 * @param purpose what is the purpose that the signature should have?
1333 * @param validate block to validate (size, purpose, data)
1334 * @param sig signature that is being validated
1335 * @param publicKey public key of the signer
1336 * @returns GNUNET_OK if ok, GNUNET_SYSERR if invalid
1337 */
1338int
1339GNUNET_CRYPTO_rsa_verify (uint32_t purpose,
1340 const struct GNUNET_CRYPTO_RsaSignaturePurpose
1341 *validate,
1342 const struct GNUNET_CRYPTO_RsaSignature *sig,
1343 const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded
1344 *publicKey)
1345{
1346 gcry_sexp_t data;
1347 gcry_sexp_t sigdata;
1348 size_t size;
1349 gcry_mpi_t val;
1350 gcry_sexp_t psexp;
1351 size_t erroff;
1352 int rc;
1353
1354 if (purpose != ntohl (validate->purpose))
1355 return GNUNET_SYSERR; /* purpose mismatch */
1356 size = sizeof (struct GNUNET_CRYPTO_RsaSignature);
1357 GNUNET_assert (0 ==
1358 gcry_mpi_scan (&val, GCRYMPI_FMT_USG,
1359 (const unsigned char *) sig, size, &size));
1360 GNUNET_assert (0 ==
1361 gcry_sexp_build (&sigdata, &erroff, "(sig-val(rsa(s %m)))",
1362 val));
1363 gcry_mpi_release (val);
1364 data = data_to_pkcs1 (validate);
1365 if (! (psexp = decode_public_key (publicKey)))
1366 {
1367 gcry_sexp_release (data);
1368 gcry_sexp_release (sigdata);
1369 return GNUNET_SYSERR;
1370 }
1371 rc = gcry_pk_verify (sigdata, data, psexp);
1372 gcry_sexp_release (psexp);
1373 gcry_sexp_release (data);
1374 gcry_sexp_release (sigdata);
1375 if (rc)
1376 {
1377 LOG (GNUNET_ERROR_TYPE_WARNING,
1378 _("RSA signature verification failed at %s:%d: %s\n"), __FILE__,
1379 __LINE__, gcry_strerror (rc));
1380 return GNUNET_SYSERR;
1381 }
1382 return GNUNET_OK;
1383}
1384
1385
1386/* end of crypto_rsa.c */
diff --git a/src/util/gnunet-rsa.c b/src/util/gnunet-rsa.c
deleted file mode 100644
index ab4bf2cb0..000000000
--- a/src/util/gnunet-rsa.c
+++ /dev/null
@@ -1,138 +0,0 @@
1/*
2 This file is part of GNUnet.
3 (C) 2012 Christian Grothoff (and other contributing authors)
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., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file util/gnunet-rsa.c
23 * @brief tool to manipulate RSA key files
24 * @author Christian Grothoff
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include <gcrypt.h>
29
30
31/**
32 * Flag for printing public key.
33 */
34static int print_public_key;
35
36/**
37 * Flag for printing hash of public key.
38 */
39static int print_peer_identity;
40
41/**
42 * Flag for printing short hash of public key.
43 */
44static int print_short_identity;
45
46
47/**
48 * Main function that will be run by the scheduler.
49 *
50 * @param cls closure
51 * @param args remaining command-line arguments
52 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
53 * @param cfg configuration
54 */
55static void
56run (void *cls, char *const *args, const char *cfgfile,
57 const struct GNUNET_CONFIGURATION_Handle *cfg)
58{
59 struct GNUNET_CRYPTO_RsaPrivateKey *pk;
60 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pub;
61 struct GNUNET_PeerIdentity pid;
62
63 if (NULL == args[0])
64 {
65 fprintf (stderr, _("No hostkey file specified on command line\n"));
66 return;
67 }
68 pk = GNUNET_CRYPTO_rsa_key_create_from_file (args[0]);
69 if (NULL == pk)
70 return;
71 if (print_public_key)
72 {
73 char *s;
74
75 GNUNET_CRYPTO_rsa_key_get_public (pk, &pub);
76 s = GNUNET_CRYPTO_rsa_public_key_to_string (&pub);
77 fprintf (stdout, "%s\n", s);
78 GNUNET_free (s);
79 }
80 if (print_peer_identity)
81 {
82 struct GNUNET_CRYPTO_HashAsciiEncoded enc;
83
84 GNUNET_CRYPTO_rsa_key_get_public (pk, &pub);
85 GNUNET_CRYPTO_hash (&pub, sizeof (pub), &pid.hashPubKey);
86 GNUNET_CRYPTO_hash_to_enc (&pid.hashPubKey, &enc);
87 fprintf (stdout, "%s\n", enc.encoding);
88 }
89 if (print_short_identity)
90 {
91 struct GNUNET_CRYPTO_ShortHashAsciiEncoded enc;
92 struct GNUNET_CRYPTO_ShortHashCode sh;
93
94 GNUNET_CRYPTO_rsa_key_get_public (pk, &pub);
95 GNUNET_CRYPTO_short_hash (&pub, sizeof (pub), &sh);
96 GNUNET_CRYPTO_short_hash_to_enc (&sh, &enc);
97 fprintf (stdout, "%s\n", enc.short_encoding);
98 }
99 GNUNET_CRYPTO_rsa_key_free (pk);
100}
101
102
103/**
104 * Program to manipulate RSA key files.
105 *
106 * @param argc number of arguments from the command line
107 * @param argv command line arguments
108 * @return 0 ok, 1 on error
109 */
110int
111main (int argc, char *const*argv)
112{
113 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
114 { 'p', "print-public-key", NULL,
115 gettext_noop ("print the public key in ASCII format"),
116 0, &GNUNET_GETOPT_set_one, &print_public_key },
117 { 'P', "print-peer-identity", NULL,
118 gettext_noop ("print the hash of the public key in ASCII format"),
119 0, &GNUNET_GETOPT_set_one, &print_peer_identity },
120 { 's', "print-short-identity", NULL,
121 gettext_noop ("print the short hash of the public key in ASCII format"),
122 0, &GNUNET_GETOPT_set_one, &print_short_identity },
123 GNUNET_GETOPT_OPTION_END
124 };
125 int ret;
126
127 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
128 return 2;
129
130 ret = (GNUNET_OK ==
131 GNUNET_PROGRAM_run (argc, argv, "gnunet-rsa [OPTIONS] keyfile",
132 gettext_noop ("Manipulate GNUnet private RSA key files"),
133 options, &run, NULL)) ? 0 : 1;
134 GNUNET_free ((void*) argv);
135 return ret;
136}
137
138/* end of gnunet-rsa.c */
diff --git a/src/util/test_crypto_ksk.c b/src/util/test_crypto_ksk.c
deleted file mode 100644
index f062e31f5..000000000
--- a/src/util/test_crypto_ksk.c
+++ /dev/null
@@ -1,261 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2004, 2005, 2006 Christian Grothoff (and other contributing authors)
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., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file util/test_crypto_ksk.c
23 * @brief testcase for util/crypto_ksk.c
24 * @author Christian Grothoff
25 */
26#include "platform.h"
27#include "gnunet_common.h"
28#include "gnunet_util_lib.h"
29#include "gnunet_signatures.h"
30
31
32#define TESTSTRING "Hello World\0"
33#define MAX_TESTVAL 20
34#define UNIQUE_ITER 6
35#define ITER 25
36
37
38static int
39testCorrectKey ()
40{
41 const char *want =
42 "010601000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b73c215f7a5e6b09bec55713c901786c09324a150980e014bdb0d04426934929c3b4971a9711af5455536cd6eeb8bfa004ee904972a737455f53c752987d8c82b755bc02882b44950c4acdc1672ba74c3b94d81a4c1ea3d74e7700ae5594c3a4f3c559e4bff2df6844fac302e4b66175e14dc8bad3ce44281d2fec1a1abef06301010000";
43 struct GNUNET_HashCode in;
44 struct GNUNET_CRYPTO_RsaPrivateKey *hostkey;
45 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pkey;
46 int i;
47 char out[3];
48
49 FPRINTF (stderr, "%s", "Testing KBlock key correctness");
50 GNUNET_CRYPTO_hash ("X", strlen ("X"), &in);
51 hostkey = GNUNET_CRYPTO_rsa_key_create_from_hash (&in);
52 if (hostkey == NULL)
53 {
54 GNUNET_break (0);
55 return GNUNET_SYSERR;
56 }
57 GNUNET_CRYPTO_rsa_key_get_public (hostkey, &pkey);
58 GNUNET_CRYPTO_rsa_key_free (hostkey);
59#if 0
60 for (i = 0; i < sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded); i++)
61 printf ("%02x", ((unsigned char *) &pkey)[i]);
62 printf ("\n");
63#endif
64 for (i = 0; i < sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded); i++)
65 {
66 snprintf (out, sizeof (out), "%02x", ((unsigned char *) &pkey)[i]);
67 if (0 != strncmp (out, &want[i * 2], 2))
68 {
69 FPRINTF (stderr, " Failed! Wanted %.2s but got %2s at %d\n", &want[i * 2],
70 out, i);
71 return GNUNET_SYSERR;
72 }
73 }
74 FPRINTF (stderr, "%s", " OK\n");
75 return GNUNET_OK;
76}
77
78
79static int
80testMultiKey (const char *word)
81{
82 struct GNUNET_HashCode in;
83 struct GNUNET_CRYPTO_RsaPrivateKey *hostkey;
84 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pkey;
85 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pkey1;
86 int i;
87
88 FPRINTF (stderr, "Testing KBlock key uniqueness (%s) ", word);
89 GNUNET_CRYPTO_hash (word, strlen (word), &in);
90 hostkey = GNUNET_CRYPTO_rsa_key_create_from_hash (&in);
91 if (hostkey == NULL)
92 {
93 GNUNET_break (0);
94 return GNUNET_SYSERR;
95 }
96 GNUNET_CRYPTO_rsa_key_get_public (hostkey, &pkey);
97 /*
98 * for (i=0;i<sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded);i++)
99 * printf("%02x", ((unsigned char*) &pkey)[i]);
100 * printf("\n"); */
101 GNUNET_CRYPTO_rsa_key_free (hostkey);
102 for (i = 0; i < UNIQUE_ITER; i++)
103 {
104 FPRINTF (stderr, "%s", ".");
105 hostkey = GNUNET_CRYPTO_rsa_key_create_from_hash (&in);
106 if (hostkey == NULL)
107 {
108 GNUNET_break (0);
109 FPRINTF (stderr, "%s", " ERROR\n");
110 return GNUNET_SYSERR;
111 }
112 GNUNET_CRYPTO_rsa_key_get_public (hostkey, &pkey1);
113 GNUNET_CRYPTO_rsa_key_free (hostkey);
114 if (0 !=
115 memcmp (&pkey, &pkey1,
116 sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded)))
117 {
118 GNUNET_break (0);
119 FPRINTF (stderr, "%s", " ERROR\n");
120 return GNUNET_SYSERR;
121 }
122 }
123 FPRINTF (stderr, "%s", " OK\n");
124 return GNUNET_OK;
125}
126
127
128static int
129testEncryptDecrypt (struct GNUNET_CRYPTO_RsaPrivateKey *hostkey)
130{
131 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pkey;
132 struct GNUNET_CRYPTO_RsaEncryptedData target;
133 char result[MAX_TESTVAL];
134 int i;
135 struct GNUNET_TIME_Absolute start;
136 int ok;
137
138 FPRINTF (stderr, "%s", "W");
139 GNUNET_CRYPTO_rsa_key_get_public (hostkey, &pkey);
140
141 ok = 0;
142 start = GNUNET_TIME_absolute_get ();
143 for (i = 0; i < ITER; i++)
144 {
145 FPRINTF (stderr, "%s", ".");
146 if (GNUNET_SYSERR ==
147 GNUNET_CRYPTO_rsa_encrypt (TESTSTRING, strlen (TESTSTRING) + 1, &pkey,
148 &target))
149 {
150 FPRINTF (stderr, "%s", "GNUNET_CRYPTO_rsa_encrypt returned SYSERR\n");
151 ok++;
152 continue;
153 }
154 if (-1 ==
155 GNUNET_CRYPTO_rsa_decrypt (hostkey, &target, result,
156 strlen (TESTSTRING) + 1))
157 {
158 FPRINTF (stderr, "%s", "GNUNET_CRYPTO_rsa_decrypt returned SYSERR\n");
159 ok++;
160 continue;
161 }
162 if (strncmp (TESTSTRING, result, strlen (TESTSTRING)) != 0)
163 {
164 printf ("%s != %.*s - testEncryptDecrypt failed!\n", TESTSTRING,
165 MAX_TESTVAL, result);
166 ok++;
167 continue;
168 }
169 }
170 printf ("%d RSA encrypt/decrypt operations %s (%d failures)\n",
171 ITER,
172 GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (start), GNUNET_YES),
173 ok);
174 if (ok == 0)
175 return GNUNET_OK;
176 else
177 return GNUNET_SYSERR;
178}
179
180static int
181testSignVerify (struct GNUNET_CRYPTO_RsaPrivateKey *hostkey)
182{
183 struct GNUNET_CRYPTO_RsaSignature sig;
184 struct GNUNET_CRYPTO_RsaSignaturePurpose purp;
185 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pkey;
186 int i;
187 struct GNUNET_TIME_Absolute start;
188 int ok = GNUNET_OK;
189
190 FPRINTF (stderr, "%s", "W");
191 GNUNET_CRYPTO_rsa_key_get_public (hostkey, &pkey);
192 start = GNUNET_TIME_absolute_get ();
193 purp.size = htonl (sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose));
194 purp.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TEST);
195 for (i = 0; i < ITER; i++)
196 {
197 FPRINTF (stderr, "%s", ".");
198 if (GNUNET_SYSERR == GNUNET_CRYPTO_rsa_sign (hostkey, &purp, &sig))
199 {
200 FPRINTF (stderr, "%s", "GNUNET_CRYPTO_rsa_sign returned SYSERR\n");
201 ok = GNUNET_SYSERR;
202 continue;
203 }
204 if (GNUNET_SYSERR ==
205 GNUNET_CRYPTO_rsa_verify (GNUNET_SIGNATURE_PURPOSE_TEST, &purp, &sig,
206 &pkey))
207 {
208 printf ("GNUNET_CRYPTO_rsa_verify failed!\n");
209 ok = GNUNET_SYSERR;
210 continue;
211 }
212 if (GNUNET_SYSERR !=
213 GNUNET_CRYPTO_rsa_verify (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_PONG_OWN,
214 &purp, &sig, &pkey))
215 {
216 printf ("GNUNET_CRYPTO_rsa_verify failed to fail!\n");
217 ok = GNUNET_SYSERR;
218 continue;
219 }
220 }
221 printf ("%d RSA sign/verify operations %s\n",
222 ITER,
223 GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (start), GNUNET_YES));
224 return ok;
225}
226
227
228int
229main (int argc, char *argv[])
230{
231 int failureCount = 0;
232 struct GNUNET_HashCode in;
233 struct GNUNET_CRYPTO_RsaPrivateKey *hostkey;
234
235 GNUNET_log_setup ("test-crypto-ksk", "WARNING", NULL);
236 if (GNUNET_OK != testCorrectKey ())
237 failureCount++;
238 GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_WEAK, &in);
239 hostkey = GNUNET_CRYPTO_rsa_key_create_from_hash (&in);
240 if (hostkey == NULL)
241 {
242 printf ("\nGNUNET_CRYPTO_rsa_key_create_from_hash failed!\n");
243 return 1;
244 }
245 if (GNUNET_OK != testMultiKey ("foo"))
246 failureCount++;
247 if (GNUNET_OK != testMultiKey ("bar"))
248 failureCount++;
249 if (GNUNET_OK != testEncryptDecrypt (hostkey))
250 failureCount++;
251 if (GNUNET_OK != testSignVerify (hostkey))
252 failureCount++;
253 GNUNET_CRYPTO_rsa_key_free (hostkey);
254
255 if (failureCount != 0)
256 {
257 printf ("\n\n%d TESTS FAILED!\n\n", failureCount);
258 return -1;
259 }
260 return 0;
261}
diff --git a/src/util/test_crypto_rsa.c b/src/util/test_crypto_rsa.c
deleted file mode 100644
index 6574cc970..000000000
--- a/src/util/test_crypto_rsa.c
+++ /dev/null
@@ -1,352 +0,0 @@
1/*
2 This file is part of GNUnet.
3 (C) 2002, 2003, 2004, 2006, 2009 Christian Grothoff (and other contributing authors)
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., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19
20*/
21/**
22 * @file util/test_crypto_rsa.c
23 * @brief testcase for RSA public key crypto
24 * @author Christian Grothoff
25 */
26#include "platform.h"
27#include "gnunet_common.h"
28#include "gnunet_util_lib.h"
29#include "gnunet_signatures.h"
30
31#define TESTSTRING "Hello World\0"
32#define MAX_TESTVAL sizeof(struct GNUNET_CRYPTO_AesSessionKey)
33#define ITER 25
34#define KEYFILE "/tmp/test-gnunet-crypto-rsa.key"
35
36#define PERF GNUNET_YES
37
38static struct GNUNET_CRYPTO_RsaPrivateKey *key;
39
40
41static int
42testEncryptDecrypt ()
43{
44 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pkey;
45 struct GNUNET_CRYPTO_RsaEncryptedData target;
46 char result[MAX_TESTVAL];
47 int i;
48 struct GNUNET_TIME_Absolute start;
49 int ok;
50
51 FPRINTF (stderr, "%s", "W");
52 GNUNET_CRYPTO_rsa_key_get_public (key, &pkey);
53 ok = 0;
54 start = GNUNET_TIME_absolute_get ();
55 for (i = 0; i < ITER; i++)
56 {
57 FPRINTF (stderr, "%s", ".");
58 if (GNUNET_SYSERR ==
59 GNUNET_CRYPTO_rsa_encrypt (TESTSTRING, strlen (TESTSTRING) + 1, &pkey,
60 &target))
61 {
62 FPRINTF (stderr, "%s", "GNUNET_CRYPTO_rsa_encrypt returned SYSERR\n");
63 ok++;
64 continue;
65 }
66 if (-1 ==
67 GNUNET_CRYPTO_rsa_decrypt (key, &target, result,
68 strlen (TESTSTRING) + 1))
69 {
70 FPRINTF (stderr, "%s", "GNUNET_CRYPTO_rsa_decrypt returned SYSERR\n");
71 ok++;
72 continue;
73
74 }
75 if (strncmp (TESTSTRING, result, strlen (TESTSTRING)) != 0)
76 {
77 printf ("%s != %.*s - testEncryptDecrypt failed!\n", TESTSTRING,
78 (int) MAX_TESTVAL, result);
79 ok++;
80 continue;
81 }
82 }
83 printf ("%d RSA encrypt/decrypt operations %s (%d failures)\n",
84 ITER,
85 GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (start), GNUNET_YES),
86 ok);
87 if (ok == 0)
88 return GNUNET_OK;
89 return GNUNET_SYSERR;
90}
91
92
93#if PERF
94static int
95testEncryptPerformance ()
96{
97 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pkey;
98 struct GNUNET_CRYPTO_RsaEncryptedData target;
99 int i;
100 struct GNUNET_TIME_Absolute start;
101 int ok;
102
103 FPRINTF (stderr, "%s", "W");
104 GNUNET_CRYPTO_rsa_key_get_public (key, &pkey);
105 ok = 0;
106 start = GNUNET_TIME_absolute_get ();
107 for (i = 0; i < ITER; i++)
108 {
109 FPRINTF (stderr, "%s", ".");
110 if (GNUNET_SYSERR ==
111 GNUNET_CRYPTO_rsa_encrypt (TESTSTRING, strlen (TESTSTRING) + 1, &pkey,
112 &target))
113 {
114 FPRINTF (stderr, "%s", "GNUNET_CRYPTO_rsa_encrypt returned SYSERR\n");
115 ok++;
116 continue;
117 }
118 }
119 printf ("%d RSA encrypt operations %llu ms (%d failures)\n", ITER,
120 (unsigned long long)
121 GNUNET_TIME_absolute_get_duration (start).rel_value, ok);
122 if (ok != 0)
123 return GNUNET_SYSERR;
124 return GNUNET_OK;
125}
126#endif
127
128static int
129testEncryptDecryptSK ()
130{
131 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pkey;
132 struct GNUNET_CRYPTO_RsaEncryptedData target;
133 struct GNUNET_CRYPTO_AesSessionKey insk;
134 struct GNUNET_CRYPTO_AesSessionKey outsk;
135 int i;
136 struct GNUNET_TIME_Absolute start;
137 int ok;
138
139 FPRINTF (stderr, "%s", "W");
140 GNUNET_CRYPTO_rsa_key_get_public (key, &pkey);
141 ok = 0;
142 start = GNUNET_TIME_absolute_get ();
143 for (i = 0; i < ITER; i++)
144 {
145 FPRINTF (stderr, "%s", ".");
146 GNUNET_CRYPTO_aes_create_session_key (&insk);
147 if (GNUNET_SYSERR ==
148 GNUNET_CRYPTO_rsa_encrypt (&insk,
149 sizeof (struct GNUNET_CRYPTO_AesSessionKey),
150 &pkey, &target))
151 {
152 FPRINTF (stderr, "%s", "GNUNET_CRYPTO_rsa_encrypt returned SYSERR\n");
153 ok++;
154 continue;
155 }
156 if (-1 ==
157 GNUNET_CRYPTO_rsa_decrypt (key, &target, &outsk,
158 sizeof (struct GNUNET_CRYPTO_AesSessionKey)))
159 {
160 FPRINTF (stderr, "%s", "GNUNET_CRYPTO_rsa_decrypt returned SYSERR\n");
161 ok++;
162 continue;
163 }
164 if (0 !=
165 memcmp (&insk, &outsk, sizeof (struct GNUNET_CRYPTO_AesSessionKey)))
166 {
167 printf ("testEncryptDecryptSK failed!\n");
168 ok++;
169 continue;
170 }
171 }
172 printf ("%d RSA encrypt/decrypt SK operations %s (%d failures)\n",
173 ITER,
174 GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (start), GNUNET_YES),
175 ok);
176 if (ok != 0)
177 return GNUNET_SYSERR;
178 return GNUNET_OK;
179}
180
181
182static int
183testSignVerify ()
184{
185 struct GNUNET_CRYPTO_RsaSignature sig;
186 struct GNUNET_CRYPTO_RsaSignaturePurpose purp;
187 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pkey;
188 int i;
189 struct GNUNET_TIME_Absolute start;
190 int ok = GNUNET_OK;
191
192 FPRINTF (stderr, "%s", "W");
193 GNUNET_CRYPTO_rsa_key_get_public (key, &pkey);
194 start = GNUNET_TIME_absolute_get ();
195 purp.size = htonl (sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose));
196 purp.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TEST);
197
198 for (i = 0; i < ITER; i++)
199 {
200 FPRINTF (stderr, "%s", ".");
201 if (GNUNET_SYSERR == GNUNET_CRYPTO_rsa_sign (key, &purp, &sig))
202 {
203 FPRINTF (stderr, "%s", "GNUNET_CRYPTO_rsa_sign returned SYSERR\n");
204 ok = GNUNET_SYSERR;
205 continue;
206 }
207 if (GNUNET_SYSERR ==
208 GNUNET_CRYPTO_rsa_verify (GNUNET_SIGNATURE_PURPOSE_TEST, &purp, &sig,
209 &pkey))
210 {
211 printf ("GNUNET_CRYPTO_rsa_verify failed!\n");
212 ok = GNUNET_SYSERR;
213 continue;
214 }
215 if (GNUNET_SYSERR !=
216 GNUNET_CRYPTO_rsa_verify (GNUNET_SIGNATURE_PURPOSE_TRANSPORT_PONG_OWN,
217 &purp, &sig, &pkey))
218 {
219 printf ("GNUNET_CRYPTO_rsa_verify failed to fail!\n");
220 ok = GNUNET_SYSERR;
221 continue;
222 }
223 }
224 printf ("%d RSA sign/verify operations %s\n", ITER,
225 GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (start), GNUNET_YES));
226 return ok;
227}
228
229
230#if PERF
231static int
232testSignPerformance ()
233{
234 struct GNUNET_CRYPTO_RsaSignaturePurpose purp;
235 struct GNUNET_CRYPTO_RsaSignature sig;
236 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pkey;
237 int i;
238 struct GNUNET_TIME_Absolute start;
239 int ok = GNUNET_OK;
240
241 purp.size = htonl (sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose));
242 purp.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TEST);
243 FPRINTF (stderr, "%s", "W");
244 GNUNET_CRYPTO_rsa_key_get_public (key, &pkey);
245 start = GNUNET_TIME_absolute_get ();
246 for (i = 0; i < ITER; i++)
247 {
248 FPRINTF (stderr, "%s", ".");
249 if (GNUNET_SYSERR == GNUNET_CRYPTO_rsa_sign (key, &purp, &sig))
250 {
251 FPRINTF (stderr, "%s", "GNUNET_CRYPTO_rsa_sign returned SYSERR\n");
252 ok = GNUNET_SYSERR;
253 continue;
254 }
255 }
256 printf ("%d RSA sign operations %llu ms\n", ITER,
257 (unsigned long long)
258 GNUNET_TIME_absolute_get_duration (start).rel_value);
259 return ok;
260}
261#endif
262
263
264static int
265testCreateFromFile ()
266{
267 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded p1;
268 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded p2;
269
270 key = GNUNET_CRYPTO_rsa_key_create_from_file (KEYFILE);
271 GNUNET_assert (NULL != key);
272 GNUNET_CRYPTO_rsa_key_get_public (key, &p1);
273 GNUNET_CRYPTO_rsa_key_free (key);
274 key = GNUNET_CRYPTO_rsa_key_create_from_file (KEYFILE);
275 GNUNET_assert (NULL != key);
276 GNUNET_CRYPTO_rsa_key_get_public (key, &p2);
277 GNUNET_assert (0 == memcmp (&p1, &p2, sizeof (p1)));
278 GNUNET_CRYPTO_rsa_key_free (key);
279 GNUNET_assert (0 == UNLINK (KEYFILE));
280 key = GNUNET_CRYPTO_rsa_key_create_from_file (KEYFILE);
281 GNUNET_assert (NULL != key);
282 GNUNET_CRYPTO_rsa_key_get_public (key, &p2);
283 GNUNET_assert (0 != memcmp (&p1, &p2, sizeof (p1)));
284 return GNUNET_OK;
285}
286
287
288static void
289key_cont (void *cls,
290 struct GNUNET_CRYPTO_RsaPrivateKey *pk,
291 const char *emsg)
292{
293 const char *txt = cls;
294 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pub1;
295 struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pub2;
296
297 GNUNET_assert (0 == strcmp ("ok", txt));
298 GNUNET_CRYPTO_rsa_key_get_public (pk, &pub1);
299 GNUNET_CRYPTO_rsa_key_get_public (key, &pub2);
300 GNUNET_assert (0 == memcmp (&pub1, &pub2,
301 sizeof (pub1)));
302 GNUNET_CRYPTO_rsa_key_free (pk);
303}
304
305
306static void
307test_async_creation (void *cls,
308 const struct GNUNET_SCHEDULER_TaskContext *tc)
309{
310 struct GNUNET_CRYPTO_RsaKeyGenerationContext *gc;
311
312 gc = GNUNET_CRYPTO_rsa_key_create_start (KEYFILE,
313 &key_cont,
314 (void*) "bug");
315 GNUNET_CRYPTO_rsa_key_create_stop (gc);
316 gc = GNUNET_CRYPTO_rsa_key_create_start (KEYFILE,
317 &key_cont,
318 (void*) "ok");
319}
320
321
322int
323main (int argc, char *argv[])
324{
325 int failureCount = 0;
326
327 GNUNET_log_setup ("test-crypto-rsa", "WARNING", NULL);
328 if (GNUNET_OK != testCreateFromFile ())
329 failureCount++;
330 GNUNET_SCHEDULER_run (&test_async_creation, NULL);
331#if PERF
332 if (GNUNET_OK != testEncryptPerformance ())
333 failureCount++;
334 if (GNUNET_OK != testSignPerformance ())
335 failureCount++;
336#endif
337 if (GNUNET_OK != testEncryptDecryptSK ())
338 failureCount++;
339 if (GNUNET_OK != testEncryptDecrypt ())
340 failureCount++;
341 if (GNUNET_OK != testSignVerify ())
342 failureCount++;
343 GNUNET_CRYPTO_rsa_key_free (key);
344 GNUNET_assert (0 == UNLINK (KEYFILE));
345
346 if (failureCount != 0)
347 {
348 printf ("\n\n%d TESTS FAILED!\n\n", failureCount);
349 return -1;
350 }
351 return 0;
352} /* end of main */