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