diff options
Diffstat (limited to 'src/lib/util/crypto_rsa.c')
-rw-r--r-- | src/lib/util/crypto_rsa.c | 1290 |
1 files changed, 1290 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..aeae3de8f --- /dev/null +++ b/src/lib/util/crypto_rsa.c | |||
@@ -0,0 +1,1290 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | Copyright (C) 2014,2016,2019,2023 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 ( | ||
182 | const struct 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 message the message to sign | ||
749 | * @param message_size number of bytes in @a message | ||
750 | * @param pkey the public key of the signer | ||
751 | * @param rsize If not NULL, the number of bytes actually stored in buffer | ||
752 | * @return MPI value set to the FDH, NULL if RSA key is malicious | ||
753 | */ | ||
754 | static gcry_mpi_t | ||
755 | rsa_full_domain_hash (const struct GNUNET_CRYPTO_RsaPublicKey *pkey, | ||
756 | const void *message, | ||
757 | size_t message_size) | ||
758 | { | ||
759 | gcry_mpi_t r; | ||
760 | gcry_mpi_t n; | ||
761 | void *xts; | ||
762 | size_t xts_len; | ||
763 | int ok; | ||
764 | |||
765 | /* Extract the composite n from the RSA public key */ | ||
766 | GNUNET_assert (0 == | ||
767 | key_from_sexp (&n, | ||
768 | pkey->sexp, | ||
769 | "rsa", | ||
770 | "n")); | ||
771 | /* Assert that it at least looks like an RSA key */ | ||
772 | GNUNET_assert (0 == | ||
773 | gcry_mpi_get_flag (n, | ||
774 | GCRYMPI_FLAG_OPAQUE)); | ||
775 | |||
776 | /* We key with the public denomination key as a homage to RSA-PSS by * | ||
777 | * Mihir Bellare and Phillip Rogaway. Doing this lowers the degree * | ||
778 | * of the hypothetical polyomial-time attack on RSA-KTI created by a * | ||
779 | * polynomial-time one-more forgary attack. Yey seeding! */ | ||
780 | xts_len = GNUNET_CRYPTO_rsa_public_key_encode (pkey, | ||
781 | &xts); | ||
782 | |||
783 | GNUNET_CRYPTO_kdf_mod_mpi (&r, | ||
784 | n, | ||
785 | xts, xts_len, | ||
786 | message, message_size, | ||
787 | "RSA-FDA FTpsW!"); | ||
788 | GNUNET_free (xts); | ||
789 | ok = rsa_gcd_validate (r, n); | ||
790 | gcry_mpi_release (n); | ||
791 | if (ok) | ||
792 | return r; | ||
793 | gcry_mpi_release (r); | ||
794 | return NULL; | ||
795 | } | ||
796 | |||
797 | |||
798 | void | ||
799 | GNUNET_CRYPTO_rsa_blinded_message_free ( | ||
800 | struct GNUNET_CRYPTO_RsaBlindedMessage *bm) | ||
801 | { | ||
802 | GNUNET_free (bm->blinded_msg); | ||
803 | } | ||
804 | |||
805 | |||
806 | enum GNUNET_GenericReturnValue | ||
807 | GNUNET_CRYPTO_rsa_blind (const void *message, | ||
808 | size_t message_size, | ||
809 | const struct GNUNET_CRYPTO_RsaBlindingKeySecret *bks, | ||
810 | struct GNUNET_CRYPTO_RsaPublicKey *pkey, | ||
811 | struct GNUNET_CRYPTO_RsaBlindedMessage *bm) | ||
812 | { | ||
813 | struct RsaBlindingKey *bkey; | ||
814 | gcry_mpi_t data; | ||
815 | gcry_mpi_t ne[2]; | ||
816 | gcry_mpi_t r_e; | ||
817 | gcry_mpi_t data_r_e; | ||
818 | int ret; | ||
819 | |||
820 | BENCHMARK_START (rsa_blind); | ||
821 | ret = key_from_sexp (ne, | ||
822 | pkey->sexp, | ||
823 | "public-key", | ||
824 | "ne"); | ||
825 | if (0 != ret) | ||
826 | ret = key_from_sexp (ne, | ||
827 | pkey->sexp, | ||
828 | "rsa", | ||
829 | "ne"); | ||
830 | if (0 != ret) | ||
831 | { | ||
832 | GNUNET_break (0); | ||
833 | bm->blinded_msg = NULL; | ||
834 | bm->blinded_msg_size = 0; | ||
835 | BENCHMARK_END (rsa_blind); | ||
836 | return GNUNET_NO; | ||
837 | } | ||
838 | |||
839 | data = rsa_full_domain_hash (pkey, | ||
840 | message, | ||
841 | message_size); | ||
842 | if (NULL == data) | ||
843 | goto rsa_gcd_validate_failure; | ||
844 | bkey = rsa_blinding_key_derive (pkey, | ||
845 | bks); | ||
846 | if (NULL == bkey) | ||
847 | { | ||
848 | gcry_mpi_release (data); | ||
849 | goto rsa_gcd_validate_failure; | ||
850 | } | ||
851 | r_e = gcry_mpi_new (0); | ||
852 | gcry_mpi_powm (r_e, | ||
853 | bkey->r, | ||
854 | ne[1], | ||
855 | ne[0]); | ||
856 | data_r_e = gcry_mpi_new (0); | ||
857 | gcry_mpi_mulm (data_r_e, | ||
858 | data, | ||
859 | r_e, | ||
860 | ne[0]); | ||
861 | gcry_mpi_release (data); | ||
862 | gcry_mpi_release (ne[0]); | ||
863 | gcry_mpi_release (ne[1]); | ||
864 | gcry_mpi_release (r_e); | ||
865 | rsa_blinding_key_free (bkey); | ||
866 | |||
867 | bm->blinded_msg_size | ||
868 | = numeric_mpi_alloc_n_print (data_r_e, | ||
869 | (char **) &bm->blinded_msg); | ||
870 | gcry_mpi_release (data_r_e); | ||
871 | |||
872 | BENCHMARK_END (rsa_blind); | ||
873 | return GNUNET_YES; | ||
874 | |||
875 | rsa_gcd_validate_failure: | ||
876 | /* We know the RSA key is malicious here, so warn the wallet. */ | ||
877 | /* GNUNET_break_op (0); */ | ||
878 | gcry_mpi_release (ne[0]); | ||
879 | gcry_mpi_release (ne[1]); | ||
880 | bm->blinded_msg = NULL; | ||
881 | bm->blinded_msg_size = 0; | ||
882 | BENCHMARK_END (rsa_blind); | ||
883 | return GNUNET_NO; | ||
884 | } | ||
885 | |||
886 | |||
887 | /** | ||
888 | * Convert an MPI to an S-expression suitable for signature operations. | ||
889 | * | ||
890 | * @param value pointer to the data to convert | ||
891 | * @return converted s-expression | ||
892 | */ | ||
893 | static gcry_sexp_t | ||
894 | mpi_to_sexp (gcry_mpi_t value) | ||
895 | { | ||
896 | gcry_sexp_t data = NULL; | ||
897 | |||
898 | GNUNET_assert (0 == | ||
899 | gcry_sexp_build (&data, | ||
900 | NULL, | ||
901 | "(data (flags raw) (value %M))", | ||
902 | value)); | ||
903 | return data; | ||
904 | } | ||
905 | |||
906 | |||
907 | /** | ||
908 | * Sign the given MPI. | ||
909 | * | ||
910 | * @param key private key to use for the signing | ||
911 | * @param value the MPI to sign | ||
912 | * @return NULL on error, signature on success | ||
913 | */ | ||
914 | static struct GNUNET_CRYPTO_RsaSignature * | ||
915 | rsa_sign_mpi (const struct GNUNET_CRYPTO_RsaPrivateKey *key, | ||
916 | gcry_mpi_t value) | ||
917 | { | ||
918 | struct GNUNET_CRYPTO_RsaSignature *sig; | ||
919 | gcry_sexp_t data; | ||
920 | gcry_sexp_t result; | ||
921 | int rc; | ||
922 | |||
923 | data = mpi_to_sexp (value); | ||
924 | |||
925 | if (0 != | ||
926 | (rc = gcry_pk_sign (&result, | ||
927 | data, | ||
928 | key->sexp))) | ||
929 | { | ||
930 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
931 | _ ("RSA signing failed at %s:%d: %s\n"), | ||
932 | __FILE__, | ||
933 | __LINE__, | ||
934 | gcry_strerror (rc)); | ||
935 | gcry_sexp_release (data); | ||
936 | GNUNET_break (0); | ||
937 | return NULL; | ||
938 | } | ||
939 | |||
940 | /* Lenstra protection was first added to libgcrypt 1.6.4 | ||
941 | * with commit c17f84bd02d7ee93845e92e20f6ddba814961588. | ||
942 | */ | ||
943 | #if GCRYPT_VERSION_NUMBER < 0x010604 | ||
944 | /* verify signature (guards against Lenstra's attack with fault injection...) */ | ||
945 | struct GNUNET_CRYPTO_RsaPublicKey *public_key = | ||
946 | GNUNET_CRYPTO_rsa_private_key_get_public (key); | ||
947 | if (0 != | ||
948 | gcry_pk_verify (result, | ||
949 | data, | ||
950 | public_key->sexp)) | ||
951 | { | ||
952 | GNUNET_break (0); | ||
953 | GNUNET_CRYPTO_rsa_public_key_free (public_key); | ||
954 | gcry_sexp_release (data); | ||
955 | gcry_sexp_release (result); | ||
956 | return NULL; | ||
957 | } | ||
958 | GNUNET_CRYPTO_rsa_public_key_free (public_key); | ||
959 | #endif | ||
960 | |||
961 | /* return signature */ | ||
962 | gcry_sexp_release (data); | ||
963 | sig = GNUNET_new (struct GNUNET_CRYPTO_RsaSignature); | ||
964 | sig->sexp = result; | ||
965 | return sig; | ||
966 | } | ||
967 | |||
968 | |||
969 | struct GNUNET_CRYPTO_RsaSignature * | ||
970 | GNUNET_CRYPTO_rsa_sign_blinded (const struct GNUNET_CRYPTO_RsaPrivateKey *key, | ||
971 | const struct GNUNET_CRYPTO_RsaBlindedMessage *bm) | ||
972 | { | ||
973 | gcry_mpi_t v = NULL; | ||
974 | struct GNUNET_CRYPTO_RsaSignature *sig; | ||
975 | |||
976 | BENCHMARK_START (rsa_sign_blinded); | ||
977 | GNUNET_assert (0 == | ||
978 | gcry_mpi_scan (&v, | ||
979 | GCRYMPI_FMT_USG, | ||
980 | bm->blinded_msg, | ||
981 | bm->blinded_msg_size, | ||
982 | NULL)); | ||
983 | sig = rsa_sign_mpi (key, | ||
984 | v); | ||
985 | gcry_mpi_release (v); | ||
986 | BENCHMARK_END (rsa_sign_blinded); | ||
987 | return sig; | ||
988 | } | ||
989 | |||
990 | |||
991 | struct GNUNET_CRYPTO_RsaSignature * | ||
992 | GNUNET_CRYPTO_rsa_sign_fdh (const struct GNUNET_CRYPTO_RsaPrivateKey *key, | ||
993 | const void *message, | ||
994 | size_t message_size) | ||
995 | { | ||
996 | struct GNUNET_CRYPTO_RsaPublicKey *pkey; | ||
997 | gcry_mpi_t v = NULL; | ||
998 | struct GNUNET_CRYPTO_RsaSignature *sig; | ||
999 | |||
1000 | pkey = GNUNET_CRYPTO_rsa_private_key_get_public (key); | ||
1001 | v = rsa_full_domain_hash (pkey, | ||
1002 | message, | ||
1003 | message_size); | ||
1004 | GNUNET_CRYPTO_rsa_public_key_free (pkey); | ||
1005 | if (NULL == v) /* rsa_gcd_validate failed meaning */ | ||
1006 | return NULL; /* our *own* RSA key is malicious. */ | ||
1007 | |||
1008 | sig = rsa_sign_mpi (key, v); | ||
1009 | gcry_mpi_release (v); | ||
1010 | return sig; | ||
1011 | } | ||
1012 | |||
1013 | |||
1014 | void | ||
1015 | GNUNET_CRYPTO_rsa_signature_free (struct GNUNET_CRYPTO_RsaSignature *sig) | ||
1016 | { | ||
1017 | gcry_sexp_release (sig->sexp); | ||
1018 | GNUNET_free (sig); | ||
1019 | } | ||
1020 | |||
1021 | |||
1022 | size_t | ||
1023 | GNUNET_CRYPTO_rsa_signature_encode ( | ||
1024 | const struct GNUNET_CRYPTO_RsaSignature *sig, | ||
1025 | void **buffer) | ||
1026 | { | ||
1027 | gcry_mpi_t s; | ||
1028 | size_t buf_size; | ||
1029 | size_t rsize; | ||
1030 | unsigned char *buf; | ||
1031 | int ret; | ||
1032 | |||
1033 | ret = key_from_sexp (&s, | ||
1034 | sig->sexp, | ||
1035 | "sig-val", | ||
1036 | "s"); | ||
1037 | if (0 != ret) | ||
1038 | ret = key_from_sexp (&s, | ||
1039 | sig->sexp, | ||
1040 | "rsa", | ||
1041 | "s"); | ||
1042 | GNUNET_assert (0 == ret); | ||
1043 | gcry_mpi_print (GCRYMPI_FMT_USG, | ||
1044 | NULL, | ||
1045 | 0, | ||
1046 | &buf_size, | ||
1047 | s); | ||
1048 | buf = GNUNET_malloc (buf_size); | ||
1049 | GNUNET_assert (0 == | ||
1050 | gcry_mpi_print (GCRYMPI_FMT_USG, | ||
1051 | buf, | ||
1052 | buf_size, | ||
1053 | &rsize, | ||
1054 | s)); | ||
1055 | GNUNET_assert (rsize == buf_size); | ||
1056 | *buffer = (void *) buf; | ||
1057 | gcry_mpi_release (s); | ||
1058 | return buf_size; | ||
1059 | } | ||
1060 | |||
1061 | |||
1062 | struct GNUNET_CRYPTO_RsaSignature * | ||
1063 | GNUNET_CRYPTO_rsa_signature_decode (const void *buf, | ||
1064 | size_t buf_size) | ||
1065 | { | ||
1066 | struct GNUNET_CRYPTO_RsaSignature *sig; | ||
1067 | gcry_mpi_t s; | ||
1068 | gcry_sexp_t data; | ||
1069 | |||
1070 | if (0 != | ||
1071 | gcry_mpi_scan (&s, | ||
1072 | GCRYMPI_FMT_USG, | ||
1073 | buf, | ||
1074 | buf_size, | ||
1075 | NULL)) | ||
1076 | { | ||
1077 | GNUNET_break_op (0); | ||
1078 | return NULL; | ||
1079 | } | ||
1080 | |||
1081 | if (0 != | ||
1082 | gcry_sexp_build (&data, | ||
1083 | NULL, | ||
1084 | "(sig-val(rsa(s %M)))", | ||
1085 | s)) | ||
1086 | { | ||
1087 | GNUNET_break (0); | ||
1088 | gcry_mpi_release (s); | ||
1089 | return NULL; | ||
1090 | } | ||
1091 | gcry_mpi_release (s); | ||
1092 | sig = GNUNET_new (struct GNUNET_CRYPTO_RsaSignature); | ||
1093 | sig->sexp = data; | ||
1094 | return sig; | ||
1095 | } | ||
1096 | |||
1097 | |||
1098 | struct GNUNET_CRYPTO_RsaPublicKey * | ||
1099 | GNUNET_CRYPTO_rsa_public_key_dup (const struct GNUNET_CRYPTO_RsaPublicKey *key) | ||
1100 | { | ||
1101 | struct GNUNET_CRYPTO_RsaPublicKey *dup; | ||
1102 | gcry_sexp_t dup_sexp; | ||
1103 | size_t erroff; | ||
1104 | |||
1105 | /* check if we really are exporting a public key */ | ||
1106 | dup_sexp = gcry_sexp_find_token (key->sexp, "public-key", 0); | ||
1107 | GNUNET_assert (NULL != dup_sexp); | ||
1108 | gcry_sexp_release (dup_sexp); | ||
1109 | /* copy the sexp */ | ||
1110 | GNUNET_assert (0 == gcry_sexp_build (&dup_sexp, &erroff, "%S", key->sexp)); | ||
1111 | dup = GNUNET_new (struct GNUNET_CRYPTO_RsaPublicKey); | ||
1112 | dup->sexp = dup_sexp; | ||
1113 | return dup; | ||
1114 | } | ||
1115 | |||
1116 | |||
1117 | struct GNUNET_CRYPTO_RsaSignature * | ||
1118 | GNUNET_CRYPTO_rsa_unblind (const struct GNUNET_CRYPTO_RsaSignature *sig, | ||
1119 | const struct GNUNET_CRYPTO_RsaBlindingKeySecret *bks, | ||
1120 | struct GNUNET_CRYPTO_RsaPublicKey *pkey) | ||
1121 | { | ||
1122 | struct RsaBlindingKey *bkey; | ||
1123 | gcry_mpi_t n; | ||
1124 | gcry_mpi_t s; | ||
1125 | gcry_mpi_t r_inv; | ||
1126 | gcry_mpi_t ubsig; | ||
1127 | int ret; | ||
1128 | struct GNUNET_CRYPTO_RsaSignature *sret; | ||
1129 | |||
1130 | BENCHMARK_START (rsa_unblind); | ||
1131 | |||
1132 | ret = key_from_sexp (&n, pkey->sexp, "public-key", "n"); | ||
1133 | if (0 != ret) | ||
1134 | ret = key_from_sexp (&n, pkey->sexp, "rsa", "n"); | ||
1135 | if (0 != ret) | ||
1136 | { | ||
1137 | GNUNET_break_op (0); | ||
1138 | return NULL; | ||
1139 | } | ||
1140 | ret = key_from_sexp (&s, sig->sexp, "sig-val", "s"); | ||
1141 | if (0 != ret) | ||
1142 | ret = key_from_sexp (&s, sig->sexp, "rsa", "s"); | ||
1143 | if (0 != ret) | ||
1144 | { | ||
1145 | gcry_mpi_release (n); | ||
1146 | GNUNET_break_op (0); | ||
1147 | return NULL; | ||
1148 | } | ||
1149 | |||
1150 | bkey = rsa_blinding_key_derive (pkey, bks); | ||
1151 | if (NULL == bkey) | ||
1152 | { | ||
1153 | /* RSA key is malicious since rsa_gcd_validate failed here. | ||
1154 | * It should have failed during GNUNET_CRYPTO_rsa_blind too though, | ||
1155 | * so the exchange is being malicious in an unfamilair way, maybe | ||
1156 | * just trying to crash us. */ | ||
1157 | GNUNET_break_op (0); | ||
1158 | gcry_mpi_release (n); | ||
1159 | gcry_mpi_release (s); | ||
1160 | return NULL; | ||
1161 | } | ||
1162 | |||
1163 | r_inv = gcry_mpi_new (0); | ||
1164 | if (1 != | ||
1165 | gcry_mpi_invm (r_inv, | ||
1166 | bkey->r, | ||
1167 | n)) | ||
1168 | { | ||
1169 | /* We cannot find r mod n, so gcd(r,n) != 1, which should get * | ||
1170 | * caught above, but we handle it the same here. */ | ||
1171 | GNUNET_break_op (0); | ||
1172 | gcry_mpi_release (r_inv); | ||
1173 | rsa_blinding_key_free (bkey); | ||
1174 | gcry_mpi_release (n); | ||
1175 | gcry_mpi_release (s); | ||
1176 | return NULL; | ||
1177 | } | ||
1178 | |||
1179 | ubsig = gcry_mpi_new (0); | ||
1180 | gcry_mpi_mulm (ubsig, s, r_inv, n); | ||
1181 | gcry_mpi_release (n); | ||
1182 | gcry_mpi_release (r_inv); | ||
1183 | gcry_mpi_release (s); | ||
1184 | rsa_blinding_key_free (bkey); | ||
1185 | |||
1186 | sret = GNUNET_new (struct GNUNET_CRYPTO_RsaSignature); | ||
1187 | GNUNET_assert (0 == | ||
1188 | gcry_sexp_build (&sret->sexp, | ||
1189 | NULL, | ||
1190 | "(sig-val (rsa (s %M)))", | ||
1191 | ubsig)); | ||
1192 | gcry_mpi_release (ubsig); | ||
1193 | BENCHMARK_END (rsa_unblind); | ||
1194 | return sret; | ||
1195 | } | ||
1196 | |||
1197 | |||
1198 | enum GNUNET_GenericReturnValue | ||
1199 | GNUNET_CRYPTO_rsa_verify (const void *message, | ||
1200 | size_t message_size, | ||
1201 | const struct GNUNET_CRYPTO_RsaSignature *sig, | ||
1202 | const struct GNUNET_CRYPTO_RsaPublicKey *pkey) | ||
1203 | { | ||
1204 | gcry_sexp_t data; | ||
1205 | gcry_mpi_t r; | ||
1206 | int rc; | ||
1207 | |||
1208 | BENCHMARK_START (rsa_verify); | ||
1209 | |||
1210 | r = rsa_full_domain_hash (pkey, | ||
1211 | message, | ||
1212 | message_size); | ||
1213 | if (NULL == r) | ||
1214 | { | ||
1215 | GNUNET_break_op (0); | ||
1216 | /* RSA key is malicious since rsa_gcd_validate failed here. | ||
1217 | * It should have failed during GNUNET_CRYPTO_rsa_blind too though, | ||
1218 | * so the exchange is being malicious in an unfamilair way, maybe | ||
1219 | * just trying to crash us. Arguably, we've only an internal error | ||
1220 | * though because we should've detected this in our previous call | ||
1221 | * to GNUNET_CRYPTO_rsa_unblind. */// | ||
1222 | return GNUNET_NO; | ||
1223 | } | ||
1224 | |||
1225 | data = mpi_to_sexp (r); | ||
1226 | gcry_mpi_release (r); | ||
1227 | |||
1228 | rc = gcry_pk_verify (sig->sexp, | ||
1229 | data, | ||
1230 | pkey->sexp); | ||
1231 | gcry_sexp_release (data); | ||
1232 | if (0 != rc) | ||
1233 | { | ||
1234 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
1235 | _ ("RSA signature verification failed at %s:%d: %s\n"), | ||
1236 | __FILE__, | ||
1237 | __LINE__, | ||
1238 | gcry_strerror (rc)); | ||
1239 | BENCHMARK_END (rsa_verify); | ||
1240 | return GNUNET_SYSERR; | ||
1241 | } | ||
1242 | BENCHMARK_END (rsa_verify); | ||
1243 | return GNUNET_OK; | ||
1244 | } | ||
1245 | |||
1246 | |||
1247 | struct GNUNET_CRYPTO_RsaPrivateKey * | ||
1248 | GNUNET_CRYPTO_rsa_private_key_dup ( | ||
1249 | const struct GNUNET_CRYPTO_RsaPrivateKey *key) | ||
1250 | { | ||
1251 | struct GNUNET_CRYPTO_RsaPrivateKey *dup; | ||
1252 | gcry_sexp_t dup_sexp; | ||
1253 | size_t erroff; | ||
1254 | |||
1255 | /* check if we really are exporting a private key */ | ||
1256 | dup_sexp = gcry_sexp_find_token (key->sexp, "private-key", 0); | ||
1257 | GNUNET_assert (NULL != dup_sexp); | ||
1258 | gcry_sexp_release (dup_sexp); | ||
1259 | /* copy the sexp */ | ||
1260 | GNUNET_assert (0 == gcry_sexp_build (&dup_sexp, &erroff, "%S", key->sexp)); | ||
1261 | dup = GNUNET_new (struct GNUNET_CRYPTO_RsaPrivateKey); | ||
1262 | dup->sexp = dup_sexp; | ||
1263 | return dup; | ||
1264 | } | ||
1265 | |||
1266 | |||
1267 | struct GNUNET_CRYPTO_RsaSignature * | ||
1268 | GNUNET_CRYPTO_rsa_signature_dup (const struct GNUNET_CRYPTO_RsaSignature *sig) | ||
1269 | { | ||
1270 | struct GNUNET_CRYPTO_RsaSignature *dup; | ||
1271 | gcry_sexp_t dup_sexp; | ||
1272 | size_t erroff; | ||
1273 | gcry_mpi_t s; | ||
1274 | int ret; | ||
1275 | |||
1276 | /* verify that this is an RSA signature */ | ||
1277 | ret = key_from_sexp (&s, sig->sexp, "sig-val", "s"); | ||
1278 | if (0 != ret) | ||
1279 | ret = key_from_sexp (&s, sig->sexp, "rsa", "s"); | ||
1280 | GNUNET_assert (0 == ret); | ||
1281 | gcry_mpi_release (s); | ||
1282 | /* copy the sexp */ | ||
1283 | GNUNET_assert (0 == gcry_sexp_build (&dup_sexp, &erroff, "%S", sig->sexp)); | ||
1284 | dup = GNUNET_new (struct GNUNET_CRYPTO_RsaSignature); | ||
1285 | dup->sexp = dup_sexp; | ||
1286 | return dup; | ||
1287 | } | ||
1288 | |||
1289 | |||
1290 | /* end of crypto_rsa.c */ | ||