diff options
Diffstat (limited to 'src/util/crypto_rsa.c')
-rw-r--r-- | src/util/crypto_rsa.c | 1262 |
1 files changed, 0 insertions, 1262 deletions
diff --git a/src/util/crypto_rsa.c b/src/util/crypto_rsa.c deleted file mode 100644 index 4b8e5a5ce..000000000 --- a/src/util/crypto_rsa.c +++ /dev/null | |||
@@ -1,1262 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | Copyright (C) 2014,2016,2019 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your 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 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file util/crypto_rsa.c | ||
23 | * @brief Chaum-style Blind signatures based on RSA | ||
24 | * @author Sree Harsha Totakura <sreeharsha@totakura.in> | ||
25 | * @author Christian Grothoff | ||
26 | * @author Jeffrey Burdges <burdges@gnunet.org> | ||
27 | */ | ||
28 | #include "platform.h" | ||
29 | #include <gcrypt.h> | ||
30 | #include "gnunet_crypto_lib.h" | ||
31 | #include "benchmark.h" | ||
32 | |||
33 | #define LOG(kind, ...) GNUNET_log_from (kind, "util-crypto-rsa", __VA_ARGS__) | ||
34 | |||
35 | |||
36 | /** | ||
37 | * The private information of an RSA key pair. | ||
38 | */ | ||
39 | struct GNUNET_CRYPTO_RsaPrivateKey | ||
40 | { | ||
41 | /** | ||
42 | * Libgcrypt S-expression for the RSA private key. | ||
43 | */ | ||
44 | gcry_sexp_t sexp; | ||
45 | }; | ||
46 | |||
47 | |||
48 | /** | ||
49 | * The public information of an RSA key pair. | ||
50 | */ | ||
51 | struct GNUNET_CRYPTO_RsaPublicKey | ||
52 | { | ||
53 | /** | ||
54 | * Libgcrypt S-expression for the RSA public key. | ||
55 | */ | ||
56 | gcry_sexp_t sexp; | ||
57 | }; | ||
58 | |||
59 | |||
60 | /** | ||
61 | * @brief an RSA signature | ||
62 | */ | ||
63 | struct GNUNET_CRYPTO_RsaSignature | ||
64 | { | ||
65 | /** | ||
66 | * Libgcrypt S-expression for the RSA signature. | ||
67 | */ | ||
68 | gcry_sexp_t sexp; | ||
69 | }; | ||
70 | |||
71 | |||
72 | /** | ||
73 | * @brief RSA blinding key | ||
74 | */ | ||
75 | struct RsaBlindingKey | ||
76 | { | ||
77 | /** | ||
78 | * Random value used for blinding. | ||
79 | */ | ||
80 | gcry_mpi_t r; | ||
81 | }; | ||
82 | |||
83 | |||
84 | /** | ||
85 | * Extract values from an S-expression. | ||
86 | * | ||
87 | * @param array where to store the result(s) | ||
88 | * @param sexp S-expression to parse | ||
89 | * @param topname top-level name in the S-expression that is of interest | ||
90 | * @param elems names of the elements to extract | ||
91 | * @return 0 on success | ||
92 | */ | ||
93 | static int | ||
94 | key_from_sexp (gcry_mpi_t *array, | ||
95 | gcry_sexp_t sexp, | ||
96 | const char *topname, | ||
97 | const char *elems) | ||
98 | { | ||
99 | gcry_sexp_t list; | ||
100 | gcry_sexp_t l2; | ||
101 | const char *s; | ||
102 | unsigned int idx; | ||
103 | |||
104 | if (! (list = gcry_sexp_find_token (sexp, topname, 0))) | ||
105 | return 1; | ||
106 | l2 = gcry_sexp_cadr (list); | ||
107 | gcry_sexp_release (list); | ||
108 | list = l2; | ||
109 | if (! list) | ||
110 | return 2; | ||
111 | idx = 0; | ||
112 | for (s = elems; *s; s++, idx++) | ||
113 | { | ||
114 | if (! (l2 = gcry_sexp_find_token (list, s, 1))) | ||
115 | { | ||
116 | for (unsigned int i = 0; i < idx; i++) | ||
117 | { | ||
118 | gcry_free (array[i]); | ||
119 | array[i] = NULL; | ||
120 | } | ||
121 | gcry_sexp_release (list); | ||
122 | return 3; /* required parameter not found */ | ||
123 | } | ||
124 | array[idx] = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG); | ||
125 | gcry_sexp_release (l2); | ||
126 | if (! array[idx]) | ||
127 | { | ||
128 | for (unsigned int i = 0; i < idx; i++) | ||
129 | { | ||
130 | gcry_free (array[i]); | ||
131 | array[i] = NULL; | ||
132 | } | ||
133 | gcry_sexp_release (list); | ||
134 | return 4; /* required parameter is invalid */ | ||
135 | } | ||
136 | } | ||
137 | gcry_sexp_release (list); | ||
138 | return 0; | ||
139 | } | ||
140 | |||
141 | |||
142 | struct GNUNET_CRYPTO_RsaPrivateKey * | ||
143 | GNUNET_CRYPTO_rsa_private_key_create (unsigned int len) | ||
144 | { | ||
145 | struct GNUNET_CRYPTO_RsaPrivateKey *ret; | ||
146 | gcry_sexp_t s_key; | ||
147 | gcry_sexp_t s_keyparam; | ||
148 | |||
149 | BENCHMARK_START (rsa_private_key_create); | ||
150 | |||
151 | GNUNET_assert (0 == | ||
152 | gcry_sexp_build (&s_keyparam, | ||
153 | NULL, | ||
154 | "(genkey(rsa(nbits %d)))", | ||
155 | len)); | ||
156 | GNUNET_assert (0 == | ||
157 | gcry_pk_genkey (&s_key, | ||
158 | s_keyparam)); | ||
159 | gcry_sexp_release (s_keyparam); | ||
160 | #if EXTRA_CHECKS | ||
161 | GNUNET_assert (0 == | ||
162 | gcry_pk_testkey (s_key)); | ||
163 | #endif | ||
164 | ret = GNUNET_new (struct GNUNET_CRYPTO_RsaPrivateKey); | ||
165 | ret->sexp = s_key; | ||
166 | BENCHMARK_END (rsa_private_key_create); | ||
167 | return ret; | ||
168 | } | ||
169 | |||
170 | |||
171 | void | ||
172 | GNUNET_CRYPTO_rsa_private_key_free (struct GNUNET_CRYPTO_RsaPrivateKey *key) | ||
173 | { | ||
174 | gcry_sexp_release (key->sexp); | ||
175 | GNUNET_free (key); | ||
176 | } | ||
177 | |||
178 | |||
179 | size_t | ||
180 | GNUNET_CRYPTO_rsa_private_key_encode (const struct | ||
181 | GNUNET_CRYPTO_RsaPrivateKey *key, | ||
182 | void **buffer) | ||
183 | { | ||
184 | size_t n; | ||
185 | char *b; | ||
186 | |||
187 | n = gcry_sexp_sprint (key->sexp, | ||
188 | GCRYSEXP_FMT_DEFAULT, | ||
189 | NULL, | ||
190 | 0); | ||
191 | b = GNUNET_malloc (n); | ||
192 | GNUNET_assert ((n - 1) == /* since the last byte is \0 */ | ||
193 | gcry_sexp_sprint (key->sexp, | ||
194 | GCRYSEXP_FMT_DEFAULT, | ||
195 | b, | ||
196 | n)); | ||
197 | *buffer = b; | ||
198 | return n; | ||
199 | } | ||
200 | |||
201 | |||
202 | struct GNUNET_CRYPTO_RsaPrivateKey * | ||
203 | GNUNET_CRYPTO_rsa_private_key_decode (const void *buf, | ||
204 | size_t buf_size) | ||
205 | { | ||
206 | struct GNUNET_CRYPTO_RsaPrivateKey *key; | ||
207 | |||
208 | key = GNUNET_new (struct GNUNET_CRYPTO_RsaPrivateKey); | ||
209 | if (0 != | ||
210 | gcry_sexp_new (&key->sexp, | ||
211 | buf, | ||
212 | buf_size, | ||
213 | 0)) | ||
214 | { | ||
215 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
216 | "Decoded private key is not valid\n"); | ||
217 | GNUNET_free (key); | ||
218 | return NULL; | ||
219 | } | ||
220 | if (0 != gcry_pk_testkey (key->sexp)) | ||
221 | { | ||
222 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
223 | "Decoded private key is not valid\n"); | ||
224 | GNUNET_CRYPTO_rsa_private_key_free (key); | ||
225 | return NULL; | ||
226 | } | ||
227 | return key; | ||
228 | } | ||
229 | |||
230 | |||
231 | struct GNUNET_CRYPTO_RsaPublicKey * | ||
232 | GNUNET_CRYPTO_rsa_private_key_get_public ( | ||
233 | const struct GNUNET_CRYPTO_RsaPrivateKey *priv) | ||
234 | { | ||
235 | struct GNUNET_CRYPTO_RsaPublicKey *pub; | ||
236 | gcry_mpi_t ne[2]; | ||
237 | int rc; | ||
238 | gcry_sexp_t result; | ||
239 | |||
240 | BENCHMARK_START (rsa_private_key_get_public); | ||
241 | |||
242 | rc = key_from_sexp (ne, priv->sexp, "public-key", "ne"); | ||
243 | if (0 != rc) | ||
244 | rc = key_from_sexp (ne, priv->sexp, "private-key", "ne"); | ||
245 | if (0 != rc) | ||
246 | rc = key_from_sexp (ne, priv->sexp, "rsa", "ne"); | ||
247 | if (0 != rc) | ||
248 | { | ||
249 | GNUNET_break_op (0); | ||
250 | return NULL; | ||
251 | } | ||
252 | rc = gcry_sexp_build (&result, | ||
253 | NULL, | ||
254 | "(public-key(rsa(n %m)(e %m)))", | ||
255 | ne[0], | ||
256 | ne[1]); | ||
257 | gcry_mpi_release (ne[0]); | ||
258 | gcry_mpi_release (ne[1]); | ||
259 | pub = GNUNET_new (struct GNUNET_CRYPTO_RsaPublicKey); | ||
260 | pub->sexp = result; | ||
261 | BENCHMARK_END (rsa_private_key_get_public); | ||
262 | return pub; | ||
263 | } | ||
264 | |||
265 | |||
266 | void | ||
267 | GNUNET_CRYPTO_rsa_public_key_free (struct GNUNET_CRYPTO_RsaPublicKey *key) | ||
268 | { | ||
269 | gcry_sexp_release (key->sexp); | ||
270 | GNUNET_free (key); | ||
271 | } | ||
272 | |||
273 | |||
274 | GNUNET_NETWORK_STRUCT_BEGIN | ||
275 | |||
276 | /** | ||
277 | * Format of the header of a serialized RSA public key. | ||
278 | */ | ||
279 | struct GNUNET_CRYPTO_RsaPublicKeyHeaderP | ||
280 | { | ||
281 | /** | ||
282 | * length of modulus 'n' in bytes, in NBO | ||
283 | */ | ||
284 | uint16_t modulus_length GNUNET_PACKED; | ||
285 | |||
286 | /** | ||
287 | * length of exponent in bytes, in NBO | ||
288 | */ | ||
289 | uint16_t public_exponent_length GNUNET_PACKED; | ||
290 | |||
291 | /* followed by variable-size modulus and | ||
292 | public exponent follows as big-endian encoded | ||
293 | integers */ | ||
294 | }; | ||
295 | |||
296 | GNUNET_NETWORK_STRUCT_END | ||
297 | |||
298 | |||
299 | bool | ||
300 | GNUNET_CRYPTO_rsa_public_key_check ( | ||
301 | const struct GNUNET_CRYPTO_RsaPublicKey *key) | ||
302 | { | ||
303 | gcry_mpi_t ne[2]; | ||
304 | int ret; | ||
305 | |||
306 | ret = key_from_sexp (ne, | ||
307 | key->sexp, | ||
308 | "public-key", | ||
309 | "ne"); | ||
310 | if (0 != ret) | ||
311 | ret = key_from_sexp (ne, | ||
312 | key->sexp, | ||
313 | "rsa", | ||
314 | "ne"); | ||
315 | if (0 != ret) | ||
316 | return false; | ||
317 | gcry_mpi_release (ne[0]); | ||
318 | gcry_mpi_release (ne[1]); | ||
319 | return true; | ||
320 | } | ||
321 | |||
322 | |||
323 | size_t | ||
324 | GNUNET_CRYPTO_rsa_public_key_encode ( | ||
325 | const struct GNUNET_CRYPTO_RsaPublicKey *key, | ||
326 | void **buffer) | ||
327 | { | ||
328 | gcry_mpi_t ne[2]; | ||
329 | size_t n_size; | ||
330 | size_t e_size; | ||
331 | size_t rsize; | ||
332 | size_t buf_size; | ||
333 | char *buf; | ||
334 | struct GNUNET_CRYPTO_RsaPublicKeyHeaderP hdr; | ||
335 | int ret; | ||
336 | |||
337 | ret = key_from_sexp (ne, | ||
338 | key->sexp, | ||
339 | "public-key", | ||
340 | "ne"); | ||
341 | if (0 != ret) | ||
342 | ret = key_from_sexp (ne, | ||
343 | key->sexp, | ||
344 | "rsa", | ||
345 | "ne"); | ||
346 | if (0 != ret) | ||
347 | { | ||
348 | GNUNET_break (0); | ||
349 | *buffer = NULL; | ||
350 | return 0; | ||
351 | } | ||
352 | gcry_mpi_print (GCRYMPI_FMT_USG, | ||
353 | NULL, | ||
354 | 0, | ||
355 | &n_size, | ||
356 | ne[0]); | ||
357 | gcry_mpi_print (GCRYMPI_FMT_USG, | ||
358 | NULL, | ||
359 | 0, | ||
360 | &e_size, | ||
361 | ne[1]); | ||
362 | if ( (e_size > UINT16_MAX) || | ||
363 | (n_size > UINT16_MAX) ) | ||
364 | { | ||
365 | GNUNET_break (0); | ||
366 | if (NULL != buffer) | ||
367 | *buffer = NULL; | ||
368 | gcry_mpi_release (ne[0]); | ||
369 | gcry_mpi_release (ne[1]); | ||
370 | return 0; | ||
371 | } | ||
372 | buf_size = n_size + e_size + sizeof (hdr); | ||
373 | if (NULL == buffer) | ||
374 | { | ||
375 | gcry_mpi_release (ne[0]); | ||
376 | gcry_mpi_release (ne[1]); | ||
377 | return buf_size; | ||
378 | } | ||
379 | buf = GNUNET_malloc (buf_size); | ||
380 | hdr.modulus_length = htons ((uint16_t) n_size); | ||
381 | hdr.public_exponent_length = htons ((uint16_t) e_size); | ||
382 | memcpy (buf, | ||
383 | &hdr, | ||
384 | sizeof (hdr)); | ||
385 | GNUNET_assert (0 == | ||
386 | gcry_mpi_print (GCRYMPI_FMT_USG, | ||
387 | (unsigned char *) &buf[sizeof (hdr)], | ||
388 | n_size, | ||
389 | &rsize, | ||
390 | ne[0])); | ||
391 | |||
392 | GNUNET_assert (0 == | ||
393 | gcry_mpi_print (GCRYMPI_FMT_USG, | ||
394 | (unsigned char *) &buf[sizeof (hdr) + n_size], | ||
395 | e_size, | ||
396 | &rsize, | ||
397 | ne[1])); | ||
398 | *buffer = buf; | ||
399 | gcry_mpi_release (ne[0]); | ||
400 | gcry_mpi_release (ne[1]); | ||
401 | return buf_size; | ||
402 | } | ||
403 | |||
404 | |||
405 | void | ||
406 | GNUNET_CRYPTO_rsa_public_key_hash (const struct GNUNET_CRYPTO_RsaPublicKey *key, | ||
407 | struct GNUNET_HashCode *hc) | ||
408 | { | ||
409 | void *buf; | ||
410 | size_t buf_size; | ||
411 | |||
412 | buf_size = GNUNET_CRYPTO_rsa_public_key_encode (key, | ||
413 | &buf); | ||
414 | GNUNET_CRYPTO_hash (buf, | ||
415 | buf_size, | ||
416 | hc); | ||
417 | GNUNET_free (buf); | ||
418 | } | ||
419 | |||
420 | |||
421 | struct GNUNET_CRYPTO_RsaPublicKey * | ||
422 | GNUNET_CRYPTO_rsa_public_key_decode (const char *buf, | ||
423 | size_t len) | ||
424 | { | ||
425 | struct GNUNET_CRYPTO_RsaPublicKey *key; | ||
426 | struct GNUNET_CRYPTO_RsaPublicKeyHeaderP hdr; | ||
427 | size_t e_size; | ||
428 | size_t n_size; | ||
429 | gcry_mpi_t n; | ||
430 | gcry_mpi_t e; | ||
431 | gcry_sexp_t data; | ||
432 | |||
433 | if (len < sizeof (hdr)) | ||
434 | { | ||
435 | GNUNET_break_op (0); | ||
436 | return NULL; | ||
437 | } | ||
438 | memcpy (&hdr, buf, sizeof (hdr)); | ||
439 | n_size = ntohs (hdr.modulus_length); | ||
440 | e_size = ntohs (hdr.public_exponent_length); | ||
441 | if (len != sizeof (hdr) + e_size + n_size) | ||
442 | { | ||
443 | GNUNET_break_op (0); | ||
444 | return NULL; | ||
445 | } | ||
446 | if (0 != | ||
447 | gcry_mpi_scan (&n, | ||
448 | GCRYMPI_FMT_USG, | ||
449 | &buf[sizeof (hdr)], | ||
450 | n_size, | ||
451 | NULL)) | ||
452 | { | ||
453 | GNUNET_break_op (0); | ||
454 | return NULL; | ||
455 | } | ||
456 | if (0 != | ||
457 | gcry_mpi_scan (&e, | ||
458 | GCRYMPI_FMT_USG, | ||
459 | &buf[sizeof (hdr) + n_size], | ||
460 | e_size, | ||
461 | NULL)) | ||
462 | { | ||
463 | GNUNET_break_op (0); | ||
464 | gcry_mpi_release (n); | ||
465 | return NULL; | ||
466 | } | ||
467 | |||
468 | if (0 != | ||
469 | gcry_sexp_build (&data, | ||
470 | NULL, | ||
471 | "(public-key(rsa(n %m)(e %m)))", | ||
472 | n, | ||
473 | e)) | ||
474 | { | ||
475 | GNUNET_break (0); | ||
476 | gcry_mpi_release (n); | ||
477 | gcry_mpi_release (e); | ||
478 | return NULL; | ||
479 | } | ||
480 | gcry_mpi_release (n); | ||
481 | gcry_mpi_release (e); | ||
482 | key = GNUNET_new (struct GNUNET_CRYPTO_RsaPublicKey); | ||
483 | key->sexp = data; | ||
484 | return key; | ||
485 | } | ||
486 | |||
487 | |||
488 | /** | ||
489 | * Test for malicious RSA key. | ||
490 | * | ||
491 | * Assuming n is an RSA modulous and r is generated using a call to | ||
492 | * GNUNET_CRYPTO_kdf_mod_mpi, if gcd(r,n) != 1 then n must be a | ||
493 | * malicious RSA key designed to deanomize the user. | ||
494 | * | ||
495 | * @param r KDF result | ||
496 | * @param n RSA modulus | ||
497 | * @return True if gcd(r,n) = 1, False means RSA key is malicious | ||
498 | */ | ||
499 | static int | ||
500 | rsa_gcd_validate (gcry_mpi_t r, | ||
501 | gcry_mpi_t n) | ||
502 | { | ||
503 | gcry_mpi_t g; | ||
504 | int t; | ||
505 | |||
506 | g = gcry_mpi_new (0); | ||
507 | t = gcry_mpi_gcd (g, r, n); | ||
508 | gcry_mpi_release (g); | ||
509 | return t; | ||
510 | } | ||
511 | |||
512 | |||
513 | /** | ||
514 | * Create a blinding key | ||
515 | * | ||
516 | * @param len length of the key in bits (e.g. 2048) | ||
517 | * @param bks pre-secret to use to derive the blinding key | ||
518 | * @return the newly created blinding key, NULL if RSA key is malicious | ||
519 | */ | ||
520 | static struct RsaBlindingKey * | ||
521 | rsa_blinding_key_derive (const struct GNUNET_CRYPTO_RsaPublicKey *pkey, | ||
522 | const struct GNUNET_CRYPTO_RsaBlindingKeySecret *bks) | ||
523 | { | ||
524 | const char *xts = "Blinding KDF extractor HMAC key"; /* Trusts bks' randomness more */ | ||
525 | struct RsaBlindingKey *blind; | ||
526 | gcry_mpi_t n; | ||
527 | |||
528 | blind = GNUNET_new (struct RsaBlindingKey); | ||
529 | |||
530 | /* Extract the composite n from the RSA public key */ | ||
531 | GNUNET_assert (0 == | ||
532 | key_from_sexp (&n, | ||
533 | pkey->sexp, | ||
534 | "rsa", | ||
535 | "n")); | ||
536 | /* Assert that it at least looks like an RSA key */ | ||
537 | GNUNET_assert (0 == | ||
538 | gcry_mpi_get_flag (n, | ||
539 | GCRYMPI_FLAG_OPAQUE)); | ||
540 | GNUNET_CRYPTO_kdf_mod_mpi (&blind->r, | ||
541 | n, | ||
542 | xts, strlen (xts), | ||
543 | bks, sizeof(*bks), | ||
544 | "Blinding KDF"); | ||
545 | if (0 == rsa_gcd_validate (blind->r, | ||
546 | n)) | ||
547 | { | ||
548 | gcry_mpi_release (blind->r); | ||
549 | GNUNET_free (blind); | ||
550 | blind = NULL; | ||
551 | } | ||
552 | gcry_mpi_release (n); | ||
553 | return blind; | ||
554 | } | ||
555 | |||
556 | |||
557 | /* | ||
558 | We originally added GNUNET_CRYPTO_kdf_mod_mpi for the benefit of the | ||
559 | previous routine. | ||
560 | |||
561 | There was previously a call to GNUNET_CRYPTO_kdf in | ||
562 | bkey = rsa_blinding_key_derive (len, bks); | ||
563 | that gives exactly len bits where | ||
564 | len = GNUNET_CRYPTO_rsa_public_key_len (pkey); | ||
565 | |||
566 | Now r = 2^(len-1)/pkey.n is the probability that a set high bit being | ||
567 | okay, meaning bkey < pkey.n. It follows that (1-r)/2 of the time bkey > | ||
568 | pkey.n making the effective bkey be | ||
569 | bkey mod pkey.n = bkey - pkey.n | ||
570 | so the effective bkey has its high bit set with probability r/2. | ||
571 | |||
572 | We expect r to be close to 1/2 if the exchange is honest, but the | ||
573 | exchange can choose r otherwise. | ||
574 | |||
575 | In blind signing, the exchange sees | ||
576 | B = bkey * S mod pkey.n | ||
577 | On deposit, the exchange sees S so they can compute bkey' = B/S mod | ||
578 | pkey.n for all B they recorded to see if bkey' has it's high bit set. | ||
579 | Also, note the exchange can compute 1/S efficiently since they know the | ||
580 | factors of pkey.n. | ||
581 | |||
582 | I suppose that happens with probability r/(1+r) if its the wrong B, not | ||
583 | completely sure. If otoh we've the right B, then we've the probability | ||
584 | r/2 of a set high bit in the effective bkey. | ||
585 | |||
586 | Interestingly, r^2-r has a maximum at the default r=1/2 anyways, giving | ||
587 | the wrong and right probabilities 1/3 and 1/4, respectively. | ||
588 | |||
589 | I feared this gives the exchange a meaningful fraction of a bit of | ||
590 | information per coin involved in the transaction. It sounds damaging if | ||
591 | numerous coins were involved. And it could run across transactions in | ||
592 | some scenarios. | ||
593 | |||
594 | We fixed this by using a more uniform deterministic pseudo-random number | ||
595 | generator for blinding factors. I do not believe this to be a problem | ||
596 | for the rsa_full_domain_hash routine, but better safe than sorry. | ||
597 | */ | ||
598 | |||
599 | |||
600 | int | ||
601 | GNUNET_CRYPTO_rsa_signature_cmp (const struct GNUNET_CRYPTO_RsaSignature *s1, | ||
602 | const struct GNUNET_CRYPTO_RsaSignature *s2) | ||
603 | { | ||
604 | void *b1; | ||
605 | void *b2; | ||
606 | size_t z1; | ||
607 | size_t z2; | ||
608 | int ret; | ||
609 | |||
610 | z1 = GNUNET_CRYPTO_rsa_signature_encode (s1, | ||
611 | &b1); | ||
612 | z2 = GNUNET_CRYPTO_rsa_signature_encode (s2, | ||
613 | &b2); | ||
614 | if (z1 != z2) | ||
615 | ret = 1; | ||
616 | else | ||
617 | ret = memcmp (b1, | ||
618 | b2, | ||
619 | z1); | ||
620 | GNUNET_free (b1); | ||
621 | GNUNET_free (b2); | ||
622 | return ret; | ||
623 | } | ||
624 | |||
625 | |||
626 | int | ||
627 | GNUNET_CRYPTO_rsa_public_key_cmp (const struct GNUNET_CRYPTO_RsaPublicKey *p1, | ||
628 | const struct GNUNET_CRYPTO_RsaPublicKey *p2) | ||
629 | { | ||
630 | void *b1; | ||
631 | void *b2; | ||
632 | size_t z1; | ||
633 | size_t z2; | ||
634 | int ret; | ||
635 | |||
636 | z1 = GNUNET_CRYPTO_rsa_public_key_encode (p1, | ||
637 | &b1); | ||
638 | z2 = GNUNET_CRYPTO_rsa_public_key_encode (p2, | ||
639 | &b2); | ||
640 | if (z1 != z2) | ||
641 | ret = 1; | ||
642 | else | ||
643 | ret = memcmp (b1, | ||
644 | b2, | ||
645 | z1); | ||
646 | GNUNET_free (b1); | ||
647 | GNUNET_free (b2); | ||
648 | return ret; | ||
649 | } | ||
650 | |||
651 | |||
652 | int | ||
653 | GNUNET_CRYPTO_rsa_private_key_cmp (const struct GNUNET_CRYPTO_RsaPrivateKey *p1, | ||
654 | const struct GNUNET_CRYPTO_RsaPrivateKey *p2) | ||
655 | { | ||
656 | void *b1; | ||
657 | void *b2; | ||
658 | size_t z1; | ||
659 | size_t z2; | ||
660 | int ret; | ||
661 | |||
662 | z1 = GNUNET_CRYPTO_rsa_private_key_encode (p1, | ||
663 | &b1); | ||
664 | z2 = GNUNET_CRYPTO_rsa_private_key_encode (p2, | ||
665 | &b2); | ||
666 | if (z1 != z2) | ||
667 | ret = 1; | ||
668 | else | ||
669 | ret = memcmp (b1, | ||
670 | b2, | ||
671 | z1); | ||
672 | GNUNET_free (b1); | ||
673 | GNUNET_free (b2); | ||
674 | return ret; | ||
675 | } | ||
676 | |||
677 | |||
678 | unsigned int | ||
679 | GNUNET_CRYPTO_rsa_public_key_len (const struct GNUNET_CRYPTO_RsaPublicKey *key) | ||
680 | { | ||
681 | gcry_mpi_t n; | ||
682 | unsigned int rval; | ||
683 | |||
684 | if (0 != key_from_sexp (&n, key->sexp, "rsa", "n")) | ||
685 | { /* Not an RSA public key */ | ||
686 | GNUNET_break (0); | ||
687 | return 0; | ||
688 | } | ||
689 | rval = gcry_mpi_get_nbits (n); | ||
690 | gcry_mpi_release (n); | ||
691 | return rval; | ||
692 | } | ||
693 | |||
694 | |||
695 | /** | ||
696 | * Destroy a blinding key | ||
697 | * | ||
698 | * @param bkey the blinding key to destroy | ||
699 | */ | ||
700 | static void | ||
701 | rsa_blinding_key_free (struct RsaBlindingKey *bkey) | ||
702 | { | ||
703 | gcry_mpi_release (bkey->r); | ||
704 | GNUNET_free (bkey); | ||
705 | } | ||
706 | |||
707 | |||
708 | /** | ||
709 | * Print an MPI to a newly created buffer | ||
710 | * | ||
711 | * @param v MPI to print. | ||
712 | * @param[out] newly allocated buffer containing the result | ||
713 | * @return number of bytes stored in @a buffer | ||
714 | */ | ||
715 | static size_t | ||
716 | numeric_mpi_alloc_n_print (gcry_mpi_t v, | ||
717 | char **buffer) | ||
718 | { | ||
719 | size_t n; | ||
720 | char *b; | ||
721 | size_t rsize; | ||
722 | |||
723 | gcry_mpi_print (GCRYMPI_FMT_USG, | ||
724 | NULL, | ||
725 | 0, | ||
726 | &n, | ||
727 | v); | ||
728 | b = GNUNET_malloc (n); | ||
729 | GNUNET_assert (0 == | ||
730 | gcry_mpi_print (GCRYMPI_FMT_USG, | ||
731 | (unsigned char *) b, | ||
732 | n, | ||
733 | &rsize, | ||
734 | v)); | ||
735 | *buffer = b; | ||
736 | return n; | ||
737 | } | ||
738 | |||
739 | |||
740 | /** | ||
741 | * Computes a full domain hash seeded by the given public key. | ||
742 | * This gives a measure of provable security to the Taler exchange | ||
743 | * against one-more forgery attacks. See: | ||
744 | * https://eprint.iacr.org/2001/002.pdf | ||
745 | * http://www.di.ens.fr/~pointche/Documents/Papers/2001_fcA.pdf | ||
746 | * | ||
747 | * @param hash initial hash of the message to sign | ||
748 | * @param pkey the public key of the signer | ||
749 | * @param rsize If not NULL, the number of bytes actually stored in buffer | ||
750 | * @return MPI value set to the FDH, NULL if RSA key is malicious | ||
751 | */ | ||
752 | static gcry_mpi_t | ||
753 | rsa_full_domain_hash (const struct GNUNET_CRYPTO_RsaPublicKey *pkey, | ||
754 | const struct GNUNET_HashCode *hash) | ||
755 | { | ||
756 | gcry_mpi_t r, n; | ||
757 | void *xts; | ||
758 | size_t xts_len; | ||
759 | int ok; | ||
760 | |||
761 | /* Extract the composite n from the RSA public key */ | ||
762 | GNUNET_assert (0 == key_from_sexp (&n, pkey->sexp, "rsa", "n")); | ||
763 | /* Assert that it at least looks like an RSA key */ | ||
764 | GNUNET_assert (0 == gcry_mpi_get_flag (n, GCRYMPI_FLAG_OPAQUE)); | ||
765 | |||
766 | /* We key with the public denomination key as a homage to RSA-PSS by * | ||
767 | * Mihir Bellare and Phillip Rogaway. Doing this lowers the degree * | ||
768 | * of the hypothetical polyomial-time attack on RSA-KTI created by a * | ||
769 | * polynomial-time one-more forgary attack. Yey seeding! */ | ||
770 | xts_len = GNUNET_CRYPTO_rsa_public_key_encode (pkey, | ||
771 | &xts); | ||
772 | |||
773 | GNUNET_CRYPTO_kdf_mod_mpi (&r, | ||
774 | n, | ||
775 | xts, xts_len, | ||
776 | hash, sizeof(*hash), | ||
777 | "RSA-FDA FTpsW!"); | ||
778 | GNUNET_free (xts); | ||
779 | ok = rsa_gcd_validate (r, n); | ||
780 | gcry_mpi_release (n); | ||
781 | if (ok) | ||
782 | return r; | ||
783 | gcry_mpi_release (r); | ||
784 | return NULL; | ||
785 | } | ||
786 | |||
787 | |||
788 | enum GNUNET_GenericReturnValue | ||
789 | GNUNET_CRYPTO_rsa_blind (const struct GNUNET_HashCode *hash, | ||
790 | const struct GNUNET_CRYPTO_RsaBlindingKeySecret *bks, | ||
791 | struct GNUNET_CRYPTO_RsaPublicKey *pkey, | ||
792 | void **buf, | ||
793 | size_t *buf_size) | ||
794 | { | ||
795 | struct RsaBlindingKey *bkey; | ||
796 | gcry_mpi_t data; | ||
797 | gcry_mpi_t ne[2]; | ||
798 | gcry_mpi_t r_e; | ||
799 | gcry_mpi_t data_r_e; | ||
800 | int ret; | ||
801 | |||
802 | BENCHMARK_START (rsa_blind); | ||
803 | |||
804 | GNUNET_assert (buf != NULL); | ||
805 | GNUNET_assert (buf_size != NULL); | ||
806 | ret = key_from_sexp (ne, pkey->sexp, "public-key", "ne"); | ||
807 | if (0 != ret) | ||
808 | ret = key_from_sexp (ne, pkey->sexp, "rsa", "ne"); | ||
809 | if (0 != ret) | ||
810 | { | ||
811 | GNUNET_break (0); | ||
812 | *buf = NULL; | ||
813 | *buf_size = 0; | ||
814 | return GNUNET_NO; | ||
815 | } | ||
816 | |||
817 | data = rsa_full_domain_hash (pkey, hash); | ||
818 | if (NULL == data) | ||
819 | goto rsa_gcd_validate_failure; | ||
820 | |||
821 | bkey = rsa_blinding_key_derive (pkey, bks); | ||
822 | if (NULL == bkey) | ||
823 | { | ||
824 | gcry_mpi_release (data); | ||
825 | goto rsa_gcd_validate_failure; | ||
826 | } | ||
827 | |||
828 | r_e = gcry_mpi_new (0); | ||
829 | gcry_mpi_powm (r_e, | ||
830 | bkey->r, | ||
831 | ne[1], | ||
832 | ne[0]); | ||
833 | data_r_e = gcry_mpi_new (0); | ||
834 | gcry_mpi_mulm (data_r_e, | ||
835 | data, | ||
836 | r_e, | ||
837 | ne[0]); | ||
838 | gcry_mpi_release (data); | ||
839 | gcry_mpi_release (ne[0]); | ||
840 | gcry_mpi_release (ne[1]); | ||
841 | gcry_mpi_release (r_e); | ||
842 | rsa_blinding_key_free (bkey); | ||
843 | |||
844 | *buf_size = numeric_mpi_alloc_n_print (data_r_e, | ||
845 | (char **) buf); | ||
846 | gcry_mpi_release (data_r_e); | ||
847 | |||
848 | BENCHMARK_END (rsa_blind); | ||
849 | |||
850 | return GNUNET_YES; | ||
851 | |||
852 | rsa_gcd_validate_failure: | ||
853 | /* We know the RSA key is malicious here, so warn the wallet. */ | ||
854 | /* GNUNET_break_op (0); */ | ||
855 | gcry_mpi_release (ne[0]); | ||
856 | gcry_mpi_release (ne[1]); | ||
857 | *buf = NULL; | ||
858 | *buf_size = 0; | ||
859 | return GNUNET_NO; | ||
860 | } | ||
861 | |||
862 | |||
863 | /** | ||
864 | * Convert an MPI to an S-expression suitable for signature operations. | ||
865 | * | ||
866 | * @param value pointer to the data to convert | ||
867 | * @return converted s-expression | ||
868 | */ | ||
869 | static gcry_sexp_t | ||
870 | mpi_to_sexp (gcry_mpi_t value) | ||
871 | { | ||
872 | gcry_sexp_t data = NULL; | ||
873 | |||
874 | GNUNET_assert (0 == | ||
875 | gcry_sexp_build (&data, | ||
876 | NULL, | ||
877 | "(data (flags raw) (value %M))", | ||
878 | value)); | ||
879 | return data; | ||
880 | } | ||
881 | |||
882 | |||
883 | /** | ||
884 | * Sign the given MPI. | ||
885 | * | ||
886 | * @param key private key to use for the signing | ||
887 | * @param value the MPI to sign | ||
888 | * @return NULL on error, signature on success | ||
889 | */ | ||
890 | static struct GNUNET_CRYPTO_RsaSignature * | ||
891 | rsa_sign_mpi (const struct GNUNET_CRYPTO_RsaPrivateKey *key, | ||
892 | gcry_mpi_t value) | ||
893 | { | ||
894 | struct GNUNET_CRYPTO_RsaSignature *sig; | ||
895 | gcry_sexp_t data; | ||
896 | gcry_sexp_t result; | ||
897 | int rc; | ||
898 | |||
899 | data = mpi_to_sexp (value); | ||
900 | |||
901 | if (0 != | ||
902 | (rc = gcry_pk_sign (&result, | ||
903 | data, | ||
904 | key->sexp))) | ||
905 | { | ||
906 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
907 | _ ("RSA signing failed at %s:%d: %s\n"), | ||
908 | __FILE__, | ||
909 | __LINE__, | ||
910 | gcry_strerror (rc)); | ||
911 | gcry_sexp_release (data); | ||
912 | GNUNET_break (0); | ||
913 | return NULL; | ||
914 | } | ||
915 | |||
916 | /* Lenstra protection was first added to libgcrypt 1.6.4 | ||
917 | * with commit c17f84bd02d7ee93845e92e20f6ddba814961588. | ||
918 | */ | ||
919 | #if GCRYPT_VERSION_NUMBER < 0x010604 | ||
920 | /* verify signature (guards against Lenstra's attack with fault injection...) */ | ||
921 | struct GNUNET_CRYPTO_RsaPublicKey *public_key = | ||
922 | GNUNET_CRYPTO_rsa_private_key_get_public (key); | ||
923 | if (0 != | ||
924 | gcry_pk_verify (result, | ||
925 | data, | ||
926 | public_key->sexp)) | ||
927 | { | ||
928 | GNUNET_break (0); | ||
929 | GNUNET_CRYPTO_rsa_public_key_free (public_key); | ||
930 | gcry_sexp_release (data); | ||
931 | gcry_sexp_release (result); | ||
932 | return NULL; | ||
933 | } | ||
934 | GNUNET_CRYPTO_rsa_public_key_free (public_key); | ||
935 | #endif | ||
936 | |||
937 | /* return signature */ | ||
938 | gcry_sexp_release (data); | ||
939 | sig = GNUNET_new (struct GNUNET_CRYPTO_RsaSignature); | ||
940 | sig->sexp = result; | ||
941 | return sig; | ||
942 | } | ||
943 | |||
944 | |||
945 | struct GNUNET_CRYPTO_RsaSignature * | ||
946 | GNUNET_CRYPTO_rsa_sign_blinded (const struct GNUNET_CRYPTO_RsaPrivateKey *key, | ||
947 | const void *msg, | ||
948 | size_t msg_len) | ||
949 | { | ||
950 | gcry_mpi_t v = NULL; | ||
951 | struct GNUNET_CRYPTO_RsaSignature *sig; | ||
952 | |||
953 | BENCHMARK_START (rsa_sign_blinded); | ||
954 | |||
955 | GNUNET_assert (0 == | ||
956 | gcry_mpi_scan (&v, | ||
957 | GCRYMPI_FMT_USG, | ||
958 | msg, | ||
959 | msg_len, | ||
960 | NULL)); | ||
961 | |||
962 | sig = rsa_sign_mpi (key, v); | ||
963 | gcry_mpi_release (v); | ||
964 | BENCHMARK_END (rsa_sign_blinded); | ||
965 | return sig; | ||
966 | } | ||
967 | |||
968 | |||
969 | struct GNUNET_CRYPTO_RsaSignature * | ||
970 | GNUNET_CRYPTO_rsa_sign_fdh (const struct GNUNET_CRYPTO_RsaPrivateKey *key, | ||
971 | const struct GNUNET_HashCode *hash) | ||
972 | { | ||
973 | struct GNUNET_CRYPTO_RsaPublicKey *pkey; | ||
974 | gcry_mpi_t v = NULL; | ||
975 | struct GNUNET_CRYPTO_RsaSignature *sig; | ||
976 | |||
977 | pkey = GNUNET_CRYPTO_rsa_private_key_get_public (key); | ||
978 | v = rsa_full_domain_hash (pkey, hash); | ||
979 | GNUNET_CRYPTO_rsa_public_key_free (pkey); | ||
980 | if (NULL == v) /* rsa_gcd_validate failed meaning */ | ||
981 | return NULL; /* our *own* RSA key is malicious. */ | ||
982 | |||
983 | sig = rsa_sign_mpi (key, v); | ||
984 | gcry_mpi_release (v); | ||
985 | return sig; | ||
986 | } | ||
987 | |||
988 | |||
989 | void | ||
990 | GNUNET_CRYPTO_rsa_signature_free (struct GNUNET_CRYPTO_RsaSignature *sig) | ||
991 | { | ||
992 | gcry_sexp_release (sig->sexp); | ||
993 | GNUNET_free (sig); | ||
994 | } | ||
995 | |||
996 | |||
997 | size_t | ||
998 | GNUNET_CRYPTO_rsa_signature_encode ( | ||
999 | const struct GNUNET_CRYPTO_RsaSignature *sig, | ||
1000 | void **buffer) | ||
1001 | { | ||
1002 | gcry_mpi_t s; | ||
1003 | size_t buf_size; | ||
1004 | size_t rsize; | ||
1005 | unsigned char *buf; | ||
1006 | int ret; | ||
1007 | |||
1008 | ret = key_from_sexp (&s, | ||
1009 | sig->sexp, | ||
1010 | "sig-val", | ||
1011 | "s"); | ||
1012 | if (0 != ret) | ||
1013 | ret = key_from_sexp (&s, | ||
1014 | sig->sexp, | ||
1015 | "rsa", | ||
1016 | "s"); | ||
1017 | GNUNET_assert (0 == ret); | ||
1018 | gcry_mpi_print (GCRYMPI_FMT_USG, | ||
1019 | NULL, | ||
1020 | 0, | ||
1021 | &buf_size, | ||
1022 | s); | ||
1023 | buf = GNUNET_malloc (buf_size); | ||
1024 | GNUNET_assert (0 == | ||
1025 | gcry_mpi_print (GCRYMPI_FMT_USG, | ||
1026 | buf, | ||
1027 | buf_size, | ||
1028 | &rsize, | ||
1029 | s)); | ||
1030 | GNUNET_assert (rsize == buf_size); | ||
1031 | *buffer = (void *) buf; | ||
1032 | gcry_mpi_release (s); | ||
1033 | return buf_size; | ||
1034 | } | ||
1035 | |||
1036 | |||
1037 | struct GNUNET_CRYPTO_RsaSignature * | ||
1038 | GNUNET_CRYPTO_rsa_signature_decode (const void *buf, | ||
1039 | size_t buf_size) | ||
1040 | { | ||
1041 | struct GNUNET_CRYPTO_RsaSignature *sig; | ||
1042 | gcry_mpi_t s; | ||
1043 | gcry_sexp_t data; | ||
1044 | |||
1045 | if (0 != | ||
1046 | gcry_mpi_scan (&s, | ||
1047 | GCRYMPI_FMT_USG, | ||
1048 | buf, | ||
1049 | buf_size, | ||
1050 | NULL)) | ||
1051 | { | ||
1052 | GNUNET_break_op (0); | ||
1053 | return NULL; | ||
1054 | } | ||
1055 | |||
1056 | if (0 != | ||
1057 | gcry_sexp_build (&data, | ||
1058 | NULL, | ||
1059 | "(sig-val(rsa(s %M)))", | ||
1060 | s)) | ||
1061 | { | ||
1062 | GNUNET_break (0); | ||
1063 | gcry_mpi_release (s); | ||
1064 | return NULL; | ||
1065 | } | ||
1066 | gcry_mpi_release (s); | ||
1067 | sig = GNUNET_new (struct GNUNET_CRYPTO_RsaSignature); | ||
1068 | sig->sexp = data; | ||
1069 | return sig; | ||
1070 | } | ||
1071 | |||
1072 | |||
1073 | struct GNUNET_CRYPTO_RsaPublicKey * | ||
1074 | GNUNET_CRYPTO_rsa_public_key_dup (const struct GNUNET_CRYPTO_RsaPublicKey *key) | ||
1075 | { | ||
1076 | struct GNUNET_CRYPTO_RsaPublicKey *dup; | ||
1077 | gcry_sexp_t dup_sexp; | ||
1078 | size_t erroff; | ||
1079 | |||
1080 | /* check if we really are exporting a public key */ | ||
1081 | dup_sexp = gcry_sexp_find_token (key->sexp, "public-key", 0); | ||
1082 | GNUNET_assert (NULL != dup_sexp); | ||
1083 | gcry_sexp_release (dup_sexp); | ||
1084 | /* copy the sexp */ | ||
1085 | GNUNET_assert (0 == gcry_sexp_build (&dup_sexp, &erroff, "%S", key->sexp)); | ||
1086 | dup = GNUNET_new (struct GNUNET_CRYPTO_RsaPublicKey); | ||
1087 | dup->sexp = dup_sexp; | ||
1088 | return dup; | ||
1089 | } | ||
1090 | |||
1091 | |||
1092 | struct GNUNET_CRYPTO_RsaSignature * | ||
1093 | GNUNET_CRYPTO_rsa_unblind (const struct GNUNET_CRYPTO_RsaSignature *sig, | ||
1094 | const struct GNUNET_CRYPTO_RsaBlindingKeySecret *bks, | ||
1095 | struct GNUNET_CRYPTO_RsaPublicKey *pkey) | ||
1096 | { | ||
1097 | struct RsaBlindingKey *bkey; | ||
1098 | gcry_mpi_t n; | ||
1099 | gcry_mpi_t s; | ||
1100 | gcry_mpi_t r_inv; | ||
1101 | gcry_mpi_t ubsig; | ||
1102 | int ret; | ||
1103 | struct GNUNET_CRYPTO_RsaSignature *sret; | ||
1104 | |||
1105 | BENCHMARK_START (rsa_unblind); | ||
1106 | |||
1107 | ret = key_from_sexp (&n, pkey->sexp, "public-key", "n"); | ||
1108 | if (0 != ret) | ||
1109 | ret = key_from_sexp (&n, pkey->sexp, "rsa", "n"); | ||
1110 | if (0 != ret) | ||
1111 | { | ||
1112 | GNUNET_break_op (0); | ||
1113 | return NULL; | ||
1114 | } | ||
1115 | ret = key_from_sexp (&s, sig->sexp, "sig-val", "s"); | ||
1116 | if (0 != ret) | ||
1117 | ret = key_from_sexp (&s, sig->sexp, "rsa", "s"); | ||
1118 | if (0 != ret) | ||
1119 | { | ||
1120 | gcry_mpi_release (n); | ||
1121 | GNUNET_break_op (0); | ||
1122 | return NULL; | ||
1123 | } | ||
1124 | |||
1125 | bkey = rsa_blinding_key_derive (pkey, bks); | ||
1126 | if (NULL == bkey) | ||
1127 | { | ||
1128 | /* RSA key is malicious since rsa_gcd_validate failed here. | ||
1129 | * It should have failed during GNUNET_CRYPTO_rsa_blind too though, | ||
1130 | * so the exchange is being malicious in an unfamilair way, maybe | ||
1131 | * just trying to crash us. */ | ||
1132 | GNUNET_break_op (0); | ||
1133 | gcry_mpi_release (n); | ||
1134 | gcry_mpi_release (s); | ||
1135 | return NULL; | ||
1136 | } | ||
1137 | |||
1138 | r_inv = gcry_mpi_new (0); | ||
1139 | if (1 != | ||
1140 | gcry_mpi_invm (r_inv, | ||
1141 | bkey->r, | ||
1142 | n)) | ||
1143 | { | ||
1144 | /* We cannot find r mod n, so gcd(r,n) != 1, which should get * | ||
1145 | * caught above, but we handle it the same here. */ | ||
1146 | GNUNET_break_op (0); | ||
1147 | gcry_mpi_release (r_inv); | ||
1148 | rsa_blinding_key_free (bkey); | ||
1149 | gcry_mpi_release (n); | ||
1150 | gcry_mpi_release (s); | ||
1151 | return NULL; | ||
1152 | } | ||
1153 | |||
1154 | ubsig = gcry_mpi_new (0); | ||
1155 | gcry_mpi_mulm (ubsig, s, r_inv, n); | ||
1156 | gcry_mpi_release (n); | ||
1157 | gcry_mpi_release (r_inv); | ||
1158 | gcry_mpi_release (s); | ||
1159 | rsa_blinding_key_free (bkey); | ||
1160 | |||
1161 | sret = GNUNET_new (struct GNUNET_CRYPTO_RsaSignature); | ||
1162 | GNUNET_assert (0 == | ||
1163 | gcry_sexp_build (&sret->sexp, | ||
1164 | NULL, | ||
1165 | "(sig-val (rsa (s %M)))", | ||
1166 | ubsig)); | ||
1167 | gcry_mpi_release (ubsig); | ||
1168 | BENCHMARK_END (rsa_unblind); | ||
1169 | return sret; | ||
1170 | } | ||
1171 | |||
1172 | |||
1173 | enum GNUNET_GenericReturnValue | ||
1174 | GNUNET_CRYPTO_rsa_verify (const struct GNUNET_HashCode *hash, | ||
1175 | const struct GNUNET_CRYPTO_RsaSignature *sig, | ||
1176 | const struct GNUNET_CRYPTO_RsaPublicKey *pkey) | ||
1177 | { | ||
1178 | gcry_sexp_t data; | ||
1179 | gcry_mpi_t r; | ||
1180 | int rc; | ||
1181 | |||
1182 | BENCHMARK_START (rsa_verify); | ||
1183 | |||
1184 | r = rsa_full_domain_hash (pkey, hash); | ||
1185 | if (NULL == r) | ||
1186 | { | ||
1187 | GNUNET_break_op (0); | ||
1188 | /* RSA key is malicious since rsa_gcd_validate failed here. | ||
1189 | * It should have failed during GNUNET_CRYPTO_rsa_blind too though, | ||
1190 | * so the exchange is being malicious in an unfamilair way, maybe | ||
1191 | * just trying to crash us. Arguably, we've only an internal error | ||
1192 | * though because we should've detected this in our previous call | ||
1193 | * to GNUNET_CRYPTO_rsa_unblind. */// | ||
1194 | return GNUNET_NO; | ||
1195 | } | ||
1196 | |||
1197 | data = mpi_to_sexp (r); | ||
1198 | gcry_mpi_release (r); | ||
1199 | |||
1200 | rc = gcry_pk_verify (sig->sexp, | ||
1201 | data, | ||
1202 | pkey->sexp); | ||
1203 | gcry_sexp_release (data); | ||
1204 | if (0 != rc) | ||
1205 | { | ||
1206 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
1207 | _ ("RSA signature verification failed at %s:%d: %s\n"), | ||
1208 | __FILE__, | ||
1209 | __LINE__, | ||
1210 | gcry_strerror (rc)); | ||
1211 | BENCHMARK_END (rsa_verify); | ||
1212 | return GNUNET_SYSERR; | ||
1213 | } | ||
1214 | BENCHMARK_END (rsa_verify); | ||
1215 | return GNUNET_OK; | ||
1216 | } | ||
1217 | |||
1218 | |||
1219 | struct GNUNET_CRYPTO_RsaPrivateKey * | ||
1220 | GNUNET_CRYPTO_rsa_private_key_dup ( | ||
1221 | const struct GNUNET_CRYPTO_RsaPrivateKey *key) | ||
1222 | { | ||
1223 | struct GNUNET_CRYPTO_RsaPrivateKey *dup; | ||
1224 | gcry_sexp_t dup_sexp; | ||
1225 | size_t erroff; | ||
1226 | |||
1227 | /* check if we really are exporting a private key */ | ||
1228 | dup_sexp = gcry_sexp_find_token (key->sexp, "private-key", 0); | ||
1229 | GNUNET_assert (NULL != dup_sexp); | ||
1230 | gcry_sexp_release (dup_sexp); | ||
1231 | /* copy the sexp */ | ||
1232 | GNUNET_assert (0 == gcry_sexp_build (&dup_sexp, &erroff, "%S", key->sexp)); | ||
1233 | dup = GNUNET_new (struct GNUNET_CRYPTO_RsaPrivateKey); | ||
1234 | dup->sexp = dup_sexp; | ||
1235 | return dup; | ||
1236 | } | ||
1237 | |||
1238 | |||
1239 | struct GNUNET_CRYPTO_RsaSignature * | ||
1240 | GNUNET_CRYPTO_rsa_signature_dup (const struct GNUNET_CRYPTO_RsaSignature *sig) | ||
1241 | { | ||
1242 | struct GNUNET_CRYPTO_RsaSignature *dup; | ||
1243 | gcry_sexp_t dup_sexp; | ||
1244 | size_t erroff; | ||
1245 | gcry_mpi_t s; | ||
1246 | int ret; | ||
1247 | |||
1248 | /* verify that this is an RSA signature */ | ||
1249 | ret = key_from_sexp (&s, sig->sexp, "sig-val", "s"); | ||
1250 | if (0 != ret) | ||
1251 | ret = key_from_sexp (&s, sig->sexp, "rsa", "s"); | ||
1252 | GNUNET_assert (0 == ret); | ||
1253 | gcry_mpi_release (s); | ||
1254 | /* copy the sexp */ | ||
1255 | GNUNET_assert (0 == gcry_sexp_build (&dup_sexp, &erroff, "%S", sig->sexp)); | ||
1256 | dup = GNUNET_new (struct GNUNET_CRYPTO_RsaSignature); | ||
1257 | dup->sexp = dup_sexp; | ||
1258 | return dup; | ||
1259 | } | ||
1260 | |||
1261 | |||
1262 | /* end of util/rsa.c */ | ||