diff options
Diffstat (limited to 'src/util/crypto_rsa.c')
-rw-r--r-- | src/util/crypto_rsa.c | 1217 |
1 files changed, 0 insertions, 1217 deletions
diff --git a/src/util/crypto_rsa.c b/src/util/crypto_rsa.c deleted file mode 100644 index 4d3de00bc..000000000 --- a/src/util/crypto_rsa.c +++ /dev/null | |||
@@ -1,1217 +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 | size_t | ||
300 | GNUNET_CRYPTO_rsa_public_key_encode ( | ||
301 | const struct GNUNET_CRYPTO_RsaPublicKey *key, | ||
302 | void **buffer) | ||
303 | { | ||
304 | gcry_mpi_t ne[2]; | ||
305 | size_t n_size; | ||
306 | size_t e_size; | ||
307 | size_t rsize; | ||
308 | size_t buf_size; | ||
309 | char *buf; | ||
310 | struct GNUNET_CRYPTO_RsaPublicKeyHeaderP hdr; | ||
311 | int ret; | ||
312 | |||
313 | ret = key_from_sexp (ne, key->sexp, "public-key", "ne"); | ||
314 | if (0 != ret) | ||
315 | ret = key_from_sexp (ne, key->sexp, "rsa", "ne"); | ||
316 | if (0 != ret) | ||
317 | { | ||
318 | GNUNET_break (0); | ||
319 | *buffer = NULL; | ||
320 | return 0; | ||
321 | } | ||
322 | gcry_mpi_print (GCRYMPI_FMT_USG, | ||
323 | NULL, | ||
324 | 0, | ||
325 | &n_size, | ||
326 | ne[0]); | ||
327 | gcry_mpi_print (GCRYMPI_FMT_USG, | ||
328 | NULL, | ||
329 | 0, | ||
330 | &e_size, | ||
331 | ne[1]); | ||
332 | if ( (e_size > UINT16_MAX) || | ||
333 | (n_size > UINT16_MAX) ) | ||
334 | { | ||
335 | GNUNET_break (0); | ||
336 | *buffer = NULL; | ||
337 | gcry_mpi_release (ne[0]); | ||
338 | gcry_mpi_release (ne[1]); | ||
339 | return 0; | ||
340 | } | ||
341 | buf_size = n_size + e_size + sizeof (hdr); | ||
342 | buf = GNUNET_malloc (buf_size); | ||
343 | hdr.modulus_length = htons ((uint16_t) n_size); | ||
344 | hdr.public_exponent_length = htons ((uint16_t) e_size); | ||
345 | memcpy (buf, &hdr, sizeof (hdr)); | ||
346 | GNUNET_assert (0 == | ||
347 | gcry_mpi_print (GCRYMPI_FMT_USG, | ||
348 | (unsigned char *) &buf[sizeof (hdr)], | ||
349 | n_size, | ||
350 | &rsize, | ||
351 | ne[0])); | ||
352 | |||
353 | GNUNET_assert (0 == | ||
354 | gcry_mpi_print (GCRYMPI_FMT_USG, | ||
355 | (unsigned char *) &buf[sizeof (hdr) + n_size], | ||
356 | e_size, | ||
357 | &rsize, | ||
358 | ne[1])); | ||
359 | *buffer = buf; | ||
360 | gcry_mpi_release (ne[0]); | ||
361 | gcry_mpi_release (ne[1]); | ||
362 | return buf_size; | ||
363 | } | ||
364 | |||
365 | |||
366 | void | ||
367 | GNUNET_CRYPTO_rsa_public_key_hash (const struct GNUNET_CRYPTO_RsaPublicKey *key, | ||
368 | struct GNUNET_HashCode *hc) | ||
369 | { | ||
370 | void *buf; | ||
371 | size_t buf_size; | ||
372 | |||
373 | buf_size = GNUNET_CRYPTO_rsa_public_key_encode (key, | ||
374 | &buf); | ||
375 | GNUNET_CRYPTO_hash (buf, | ||
376 | buf_size, | ||
377 | hc); | ||
378 | GNUNET_free (buf); | ||
379 | } | ||
380 | |||
381 | |||
382 | struct GNUNET_CRYPTO_RsaPublicKey * | ||
383 | GNUNET_CRYPTO_rsa_public_key_decode (const char *buf, | ||
384 | size_t len) | ||
385 | { | ||
386 | struct GNUNET_CRYPTO_RsaPublicKey *key; | ||
387 | struct GNUNET_CRYPTO_RsaPublicKeyHeaderP hdr; | ||
388 | size_t e_size; | ||
389 | size_t n_size; | ||
390 | gcry_mpi_t n; | ||
391 | gcry_mpi_t e; | ||
392 | gcry_sexp_t data; | ||
393 | |||
394 | if (len < sizeof (hdr)) | ||
395 | { | ||
396 | GNUNET_break_op (0); | ||
397 | return NULL; | ||
398 | } | ||
399 | memcpy (&hdr, buf, sizeof (hdr)); | ||
400 | n_size = ntohs (hdr.modulus_length); | ||
401 | e_size = ntohs (hdr.public_exponent_length); | ||
402 | if (len != sizeof (hdr) + e_size + n_size) | ||
403 | { | ||
404 | GNUNET_break_op (0); | ||
405 | return NULL; | ||
406 | } | ||
407 | if (0 != | ||
408 | gcry_mpi_scan (&n, | ||
409 | GCRYMPI_FMT_USG, | ||
410 | &buf[sizeof (hdr)], | ||
411 | n_size, | ||
412 | NULL)) | ||
413 | { | ||
414 | GNUNET_break_op (0); | ||
415 | return NULL; | ||
416 | } | ||
417 | if (0 != | ||
418 | gcry_mpi_scan (&e, | ||
419 | GCRYMPI_FMT_USG, | ||
420 | &buf[sizeof (hdr) + n_size], | ||
421 | e_size, | ||
422 | NULL)) | ||
423 | { | ||
424 | GNUNET_break_op (0); | ||
425 | gcry_mpi_release (n); | ||
426 | return NULL; | ||
427 | } | ||
428 | |||
429 | if (0 != | ||
430 | gcry_sexp_build (&data, | ||
431 | NULL, | ||
432 | "(public-key(rsa(n %m)(e %m)))", | ||
433 | n, | ||
434 | e)) | ||
435 | { | ||
436 | GNUNET_break (0); | ||
437 | gcry_mpi_release (n); | ||
438 | gcry_mpi_release (e); | ||
439 | return NULL; | ||
440 | } | ||
441 | gcry_mpi_release (n); | ||
442 | gcry_mpi_release (e); | ||
443 | key = GNUNET_new (struct GNUNET_CRYPTO_RsaPublicKey); | ||
444 | key->sexp = data; | ||
445 | return key; | ||
446 | } | ||
447 | |||
448 | |||
449 | /** | ||
450 | * Test for malicious RSA key. | ||
451 | * | ||
452 | * Assuming n is an RSA modulous and r is generated using a call to | ||
453 | * GNUNET_CRYPTO_kdf_mod_mpi, if gcd(r,n) != 1 then n must be a | ||
454 | * malicious RSA key designed to deanomize the user. | ||
455 | * | ||
456 | * @param r KDF result | ||
457 | * @param n RSA modulus | ||
458 | * @return True if gcd(r,n) = 1, False means RSA key is malicious | ||
459 | */ | ||
460 | static int | ||
461 | rsa_gcd_validate (gcry_mpi_t r, gcry_mpi_t n) | ||
462 | { | ||
463 | gcry_mpi_t g; | ||
464 | int t; | ||
465 | |||
466 | g = gcry_mpi_new (0); | ||
467 | t = gcry_mpi_gcd (g, r, n); | ||
468 | gcry_mpi_release (g); | ||
469 | return t; | ||
470 | } | ||
471 | |||
472 | |||
473 | /** | ||
474 | * Create a blinding key | ||
475 | * | ||
476 | * @param len length of the key in bits (e.g. 2048) | ||
477 | * @param bks pre-secret to use to derive the blinding key | ||
478 | * @return the newly created blinding key, NULL if RSA key is malicious | ||
479 | */ | ||
480 | static struct RsaBlindingKey * | ||
481 | rsa_blinding_key_derive (const struct GNUNET_CRYPTO_RsaPublicKey *pkey, | ||
482 | const struct GNUNET_CRYPTO_RsaBlindingKeySecret *bks) | ||
483 | { | ||
484 | char *xts = "Blinding KDF extractor HMAC key"; /* Trusts bks' randomness more */ | ||
485 | struct RsaBlindingKey *blind; | ||
486 | gcry_mpi_t n; | ||
487 | |||
488 | blind = GNUNET_new (struct RsaBlindingKey); | ||
489 | GNUNET_assert (NULL != blind); | ||
490 | |||
491 | /* Extract the composite n from the RSA public key */ | ||
492 | GNUNET_assert (0 == key_from_sexp (&n, pkey->sexp, "rsa", "n")); | ||
493 | /* Assert that it at least looks like an RSA key */ | ||
494 | GNUNET_assert (0 == gcry_mpi_get_flag (n, GCRYMPI_FLAG_OPAQUE)); | ||
495 | |||
496 | GNUNET_CRYPTO_kdf_mod_mpi (&blind->r, | ||
497 | n, | ||
498 | xts, strlen (xts), | ||
499 | bks, sizeof(*bks), | ||
500 | "Blinding KDF"); | ||
501 | if (0 == rsa_gcd_validate (blind->r, n)) | ||
502 | { | ||
503 | GNUNET_free (blind); | ||
504 | blind = NULL; | ||
505 | } | ||
506 | |||
507 | gcry_mpi_release (n); | ||
508 | return blind; | ||
509 | } | ||
510 | |||
511 | |||
512 | /* | ||
513 | We originally added GNUNET_CRYPTO_kdf_mod_mpi for the benefit of the | ||
514 | previous routine. | ||
515 | |||
516 | There was previously a call to GNUNET_CRYPTO_kdf in | ||
517 | bkey = rsa_blinding_key_derive (len, bks); | ||
518 | that gives exactly len bits where | ||
519 | len = GNUNET_CRYPTO_rsa_public_key_len (pkey); | ||
520 | |||
521 | Now r = 2^(len-1)/pkey.n is the probability that a set high bit being | ||
522 | okay, meaning bkey < pkey.n. It follows that (1-r)/2 of the time bkey > | ||
523 | pkey.n making the effective bkey be | ||
524 | bkey mod pkey.n = bkey - pkey.n | ||
525 | so the effective bkey has its high bit set with probability r/2. | ||
526 | |||
527 | We expect r to be close to 1/2 if the exchange is honest, but the | ||
528 | exchange can choose r otherwise. | ||
529 | |||
530 | In blind signing, the exchange sees | ||
531 | B = bkey * S mod pkey.n | ||
532 | On deposit, the exchange sees S so they can compute bkey' = B/S mod | ||
533 | pkey.n for all B they recorded to see if bkey' has it's high bit set. | ||
534 | Also, note the exchange can compute 1/S efficiently since they know the | ||
535 | factors of pkey.n. | ||
536 | |||
537 | I suppose that happens with probability r/(1+r) if its the wrong B, not | ||
538 | completely sure. If otoh we've the right B, then we've the probability | ||
539 | r/2 of a set high bit in the effective bkey. | ||
540 | |||
541 | Interestingly, r^2-r has a maximum at the default r=1/2 anyways, giving | ||
542 | the wrong and right probabilities 1/3 and 1/4, respectively. | ||
543 | |||
544 | I feared this gives the exchange a meaningful fraction of a bit of | ||
545 | information per coin involved in the transaction. It sounds damaging if | ||
546 | numerous coins were involved. And it could run across transactions in | ||
547 | some scenarios. | ||
548 | |||
549 | We fixed this by using a more uniform deterministic pseudo-random number | ||
550 | generator for blinding factors. I do not believe this to be a problem | ||
551 | for the rsa_full_domain_hash routine, but better safe than sorry. | ||
552 | */ | ||
553 | |||
554 | |||
555 | int | ||
556 | GNUNET_CRYPTO_rsa_signature_cmp (const struct GNUNET_CRYPTO_RsaSignature *s1, | ||
557 | const struct GNUNET_CRYPTO_RsaSignature *s2) | ||
558 | { | ||
559 | void *b1; | ||
560 | void *b2; | ||
561 | size_t z1; | ||
562 | size_t z2; | ||
563 | int ret; | ||
564 | |||
565 | z1 = GNUNET_CRYPTO_rsa_signature_encode (s1, | ||
566 | &b1); | ||
567 | z2 = GNUNET_CRYPTO_rsa_signature_encode (s2, | ||
568 | &b2); | ||
569 | if (z1 != z2) | ||
570 | ret = 1; | ||
571 | else | ||
572 | ret = memcmp (b1, | ||
573 | b2, | ||
574 | z1); | ||
575 | GNUNET_free (b1); | ||
576 | GNUNET_free (b2); | ||
577 | return ret; | ||
578 | } | ||
579 | |||
580 | |||
581 | int | ||
582 | GNUNET_CRYPTO_rsa_public_key_cmp (const struct GNUNET_CRYPTO_RsaPublicKey *p1, | ||
583 | const struct GNUNET_CRYPTO_RsaPublicKey *p2) | ||
584 | { | ||
585 | void *b1; | ||
586 | void *b2; | ||
587 | size_t z1; | ||
588 | size_t z2; | ||
589 | int ret; | ||
590 | |||
591 | z1 = GNUNET_CRYPTO_rsa_public_key_encode (p1, | ||
592 | &b1); | ||
593 | z2 = GNUNET_CRYPTO_rsa_public_key_encode (p2, | ||
594 | &b2); | ||
595 | if (z1 != z2) | ||
596 | ret = 1; | ||
597 | else | ||
598 | ret = memcmp (b1, | ||
599 | b2, | ||
600 | z1); | ||
601 | GNUNET_free (b1); | ||
602 | GNUNET_free (b2); | ||
603 | return ret; | ||
604 | } | ||
605 | |||
606 | |||
607 | int | ||
608 | GNUNET_CRYPTO_rsa_private_key_cmp (const struct GNUNET_CRYPTO_RsaPrivateKey *p1, | ||
609 | const struct GNUNET_CRYPTO_RsaPrivateKey *p2) | ||
610 | { | ||
611 | void *b1; | ||
612 | void *b2; | ||
613 | size_t z1; | ||
614 | size_t z2; | ||
615 | int ret; | ||
616 | |||
617 | z1 = GNUNET_CRYPTO_rsa_private_key_encode (p1, | ||
618 | &b1); | ||
619 | z2 = GNUNET_CRYPTO_rsa_private_key_encode (p2, | ||
620 | &b2); | ||
621 | if (z1 != z2) | ||
622 | ret = 1; | ||
623 | else | ||
624 | ret = memcmp (b1, | ||
625 | b2, | ||
626 | z1); | ||
627 | GNUNET_free (b1); | ||
628 | GNUNET_free (b2); | ||
629 | return ret; | ||
630 | } | ||
631 | |||
632 | |||
633 | unsigned int | ||
634 | GNUNET_CRYPTO_rsa_public_key_len (const struct GNUNET_CRYPTO_RsaPublicKey *key) | ||
635 | { | ||
636 | gcry_mpi_t n; | ||
637 | unsigned int rval; | ||
638 | |||
639 | if (0 != key_from_sexp (&n, key->sexp, "rsa", "n")) | ||
640 | { /* Not an RSA public key */ | ||
641 | GNUNET_break (0); | ||
642 | return 0; | ||
643 | } | ||
644 | rval = gcry_mpi_get_nbits (n); | ||
645 | gcry_mpi_release (n); | ||
646 | return rval; | ||
647 | } | ||
648 | |||
649 | |||
650 | /** | ||
651 | * Destroy a blinding key | ||
652 | * | ||
653 | * @param bkey the blinding key to destroy | ||
654 | */ | ||
655 | static void | ||
656 | rsa_blinding_key_free (struct RsaBlindingKey *bkey) | ||
657 | { | ||
658 | gcry_mpi_release (bkey->r); | ||
659 | GNUNET_free (bkey); | ||
660 | } | ||
661 | |||
662 | |||
663 | /** | ||
664 | * Print an MPI to a newly created buffer | ||
665 | * | ||
666 | * @param v MPI to print. | ||
667 | * @param[out] newly allocated buffer containing the result | ||
668 | * @return number of bytes stored in @a buffer | ||
669 | */ | ||
670 | static size_t | ||
671 | numeric_mpi_alloc_n_print (gcry_mpi_t v, | ||
672 | char **buffer) | ||
673 | { | ||
674 | size_t n; | ||
675 | char *b; | ||
676 | size_t rsize; | ||
677 | |||
678 | gcry_mpi_print (GCRYMPI_FMT_USG, | ||
679 | NULL, | ||
680 | 0, | ||
681 | &n, | ||
682 | v); | ||
683 | b = GNUNET_malloc (n); | ||
684 | GNUNET_assert (0 == | ||
685 | gcry_mpi_print (GCRYMPI_FMT_USG, | ||
686 | (unsigned char *) b, | ||
687 | n, | ||
688 | &rsize, | ||
689 | v)); | ||
690 | *buffer = b; | ||
691 | return n; | ||
692 | } | ||
693 | |||
694 | |||
695 | /** | ||
696 | * Computes a full domain hash seeded by the given public key. | ||
697 | * This gives a measure of provable security to the Taler exchange | ||
698 | * against one-more forgery attacks. See: | ||
699 | * https://eprint.iacr.org/2001/002.pdf | ||
700 | * http://www.di.ens.fr/~pointche/Documents/Papers/2001_fcA.pdf | ||
701 | * | ||
702 | * @param hash initial hash of the message to sign | ||
703 | * @param pkey the public key of the signer | ||
704 | * @param rsize If not NULL, the number of bytes actually stored in buffer | ||
705 | * @return MPI value set to the FDH, NULL if RSA key is malicious | ||
706 | */ | ||
707 | static gcry_mpi_t | ||
708 | rsa_full_domain_hash (const struct GNUNET_CRYPTO_RsaPublicKey *pkey, | ||
709 | const struct GNUNET_HashCode *hash) | ||
710 | { | ||
711 | gcry_mpi_t r, n; | ||
712 | void *xts; | ||
713 | size_t xts_len; | ||
714 | int ok; | ||
715 | |||
716 | /* Extract the composite n from the RSA public key */ | ||
717 | GNUNET_assert (0 == key_from_sexp (&n, pkey->sexp, "rsa", "n")); | ||
718 | /* Assert that it at least looks like an RSA key */ | ||
719 | GNUNET_assert (0 == gcry_mpi_get_flag (n, GCRYMPI_FLAG_OPAQUE)); | ||
720 | |||
721 | /* We key with the public denomination key as a homage to RSA-PSS by * | ||
722 | * Mihir Bellare and Phillip Rogaway. Doing this lowers the degree * | ||
723 | * of the hypothetical polyomial-time attack on RSA-KTI created by a * | ||
724 | * polynomial-time one-more forgary attack. Yey seeding! */ | ||
725 | xts_len = GNUNET_CRYPTO_rsa_public_key_encode (pkey, &xts); | ||
726 | |||
727 | GNUNET_CRYPTO_kdf_mod_mpi (&r, | ||
728 | n, | ||
729 | xts, xts_len, | ||
730 | hash, sizeof(*hash), | ||
731 | "RSA-FDA FTpsW!"); | ||
732 | GNUNET_free (xts); | ||
733 | |||
734 | ok = rsa_gcd_validate (r, n); | ||
735 | gcry_mpi_release (n); | ||
736 | if (ok) | ||
737 | return r; | ||
738 | gcry_mpi_release (r); | ||
739 | return NULL; | ||
740 | } | ||
741 | |||
742 | |||
743 | enum GNUNET_GenericReturnValue | ||
744 | GNUNET_CRYPTO_rsa_blind (const struct GNUNET_HashCode *hash, | ||
745 | const struct GNUNET_CRYPTO_RsaBlindingKeySecret *bks, | ||
746 | struct GNUNET_CRYPTO_RsaPublicKey *pkey, | ||
747 | void **buf, | ||
748 | size_t *buf_size) | ||
749 | { | ||
750 | struct RsaBlindingKey *bkey; | ||
751 | gcry_mpi_t data; | ||
752 | gcry_mpi_t ne[2]; | ||
753 | gcry_mpi_t r_e; | ||
754 | gcry_mpi_t data_r_e; | ||
755 | int ret; | ||
756 | |||
757 | BENCHMARK_START (rsa_blind); | ||
758 | |||
759 | GNUNET_assert (buf != NULL); | ||
760 | GNUNET_assert (buf_size != NULL); | ||
761 | ret = key_from_sexp (ne, pkey->sexp, "public-key", "ne"); | ||
762 | if (0 != ret) | ||
763 | ret = key_from_sexp (ne, pkey->sexp, "rsa", "ne"); | ||
764 | if (0 != ret) | ||
765 | { | ||
766 | GNUNET_break (0); | ||
767 | *buf = NULL; | ||
768 | *buf_size = 0; | ||
769 | return GNUNET_NO; | ||
770 | } | ||
771 | |||
772 | data = rsa_full_domain_hash (pkey, hash); | ||
773 | if (NULL == data) | ||
774 | goto rsa_gcd_validate_failure; | ||
775 | |||
776 | bkey = rsa_blinding_key_derive (pkey, bks); | ||
777 | if (NULL == bkey) | ||
778 | { | ||
779 | gcry_mpi_release (data); | ||
780 | goto rsa_gcd_validate_failure; | ||
781 | } | ||
782 | |||
783 | r_e = gcry_mpi_new (0); | ||
784 | gcry_mpi_powm (r_e, | ||
785 | bkey->r, | ||
786 | ne[1], | ||
787 | ne[0]); | ||
788 | data_r_e = gcry_mpi_new (0); | ||
789 | gcry_mpi_mulm (data_r_e, | ||
790 | data, | ||
791 | r_e, | ||
792 | ne[0]); | ||
793 | gcry_mpi_release (data); | ||
794 | gcry_mpi_release (ne[0]); | ||
795 | gcry_mpi_release (ne[1]); | ||
796 | gcry_mpi_release (r_e); | ||
797 | rsa_blinding_key_free (bkey); | ||
798 | |||
799 | *buf_size = numeric_mpi_alloc_n_print (data_r_e, | ||
800 | (char **) buf); | ||
801 | gcry_mpi_release (data_r_e); | ||
802 | |||
803 | BENCHMARK_END (rsa_blind); | ||
804 | |||
805 | return GNUNET_YES; | ||
806 | |||
807 | rsa_gcd_validate_failure: | ||
808 | /* We know the RSA key is malicious here, so warn the wallet. */ | ||
809 | /* GNUNET_break_op (0); */ | ||
810 | gcry_mpi_release (ne[0]); | ||
811 | gcry_mpi_release (ne[1]); | ||
812 | *buf = NULL; | ||
813 | *buf_size = 0; | ||
814 | return GNUNET_NO; | ||
815 | } | ||
816 | |||
817 | |||
818 | /** | ||
819 | * Convert an MPI to an S-expression suitable for signature operations. | ||
820 | * | ||
821 | * @param value pointer to the data to convert | ||
822 | * @return converted s-expression | ||
823 | */ | ||
824 | static gcry_sexp_t | ||
825 | mpi_to_sexp (gcry_mpi_t value) | ||
826 | { | ||
827 | gcry_sexp_t data = NULL; | ||
828 | |||
829 | GNUNET_assert (0 == | ||
830 | gcry_sexp_build (&data, | ||
831 | NULL, | ||
832 | "(data (flags raw) (value %M))", | ||
833 | value)); | ||
834 | return data; | ||
835 | } | ||
836 | |||
837 | |||
838 | /** | ||
839 | * Sign the given MPI. | ||
840 | * | ||
841 | * @param key private key to use for the signing | ||
842 | * @param value the MPI to sign | ||
843 | * @return NULL on error, signature on success | ||
844 | */ | ||
845 | static struct GNUNET_CRYPTO_RsaSignature * | ||
846 | rsa_sign_mpi (const struct GNUNET_CRYPTO_RsaPrivateKey *key, | ||
847 | gcry_mpi_t value) | ||
848 | { | ||
849 | struct GNUNET_CRYPTO_RsaSignature *sig; | ||
850 | gcry_sexp_t data; | ||
851 | gcry_sexp_t result; | ||
852 | int rc; | ||
853 | |||
854 | data = mpi_to_sexp (value); | ||
855 | |||
856 | if (0 != | ||
857 | (rc = gcry_pk_sign (&result, | ||
858 | data, | ||
859 | key->sexp))) | ||
860 | { | ||
861 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
862 | _ ("RSA signing failed at %s:%d: %s\n"), | ||
863 | __FILE__, | ||
864 | __LINE__, | ||
865 | gcry_strerror (rc)); | ||
866 | gcry_sexp_release (data); | ||
867 | GNUNET_break (0); | ||
868 | return NULL; | ||
869 | } | ||
870 | |||
871 | /* Lenstra protection was first added to libgcrypt 1.6.4 | ||
872 | * with commit c17f84bd02d7ee93845e92e20f6ddba814961588. | ||
873 | */ | ||
874 | #if GCRYPT_VERSION_NUMBER < 0x010604 | ||
875 | /* verify signature (guards against Lenstra's attack with fault injection...) */ | ||
876 | struct GNUNET_CRYPTO_RsaPublicKey *public_key = | ||
877 | GNUNET_CRYPTO_rsa_private_key_get_public (key); | ||
878 | if (0 != | ||
879 | gcry_pk_verify (result, | ||
880 | data, | ||
881 | public_key->sexp)) | ||
882 | { | ||
883 | GNUNET_break (0); | ||
884 | GNUNET_CRYPTO_rsa_public_key_free (public_key); | ||
885 | gcry_sexp_release (data); | ||
886 | gcry_sexp_release (result); | ||
887 | return NULL; | ||
888 | } | ||
889 | GNUNET_CRYPTO_rsa_public_key_free (public_key); | ||
890 | #endif | ||
891 | |||
892 | /* return signature */ | ||
893 | gcry_sexp_release (data); | ||
894 | sig = GNUNET_new (struct GNUNET_CRYPTO_RsaSignature); | ||
895 | sig->sexp = result; | ||
896 | return sig; | ||
897 | } | ||
898 | |||
899 | |||
900 | struct GNUNET_CRYPTO_RsaSignature * | ||
901 | GNUNET_CRYPTO_rsa_sign_blinded (const struct GNUNET_CRYPTO_RsaPrivateKey *key, | ||
902 | const void *msg, | ||
903 | size_t msg_len) | ||
904 | { | ||
905 | gcry_mpi_t v = NULL; | ||
906 | struct GNUNET_CRYPTO_RsaSignature *sig; | ||
907 | |||
908 | BENCHMARK_START (rsa_sign_blinded); | ||
909 | |||
910 | GNUNET_assert (0 == | ||
911 | gcry_mpi_scan (&v, | ||
912 | GCRYMPI_FMT_USG, | ||
913 | msg, | ||
914 | msg_len, | ||
915 | NULL)); | ||
916 | |||
917 | sig = rsa_sign_mpi (key, v); | ||
918 | gcry_mpi_release (v); | ||
919 | BENCHMARK_END (rsa_sign_blinded); | ||
920 | return sig; | ||
921 | } | ||
922 | |||
923 | |||
924 | struct GNUNET_CRYPTO_RsaSignature * | ||
925 | GNUNET_CRYPTO_rsa_sign_fdh (const struct GNUNET_CRYPTO_RsaPrivateKey *key, | ||
926 | const struct GNUNET_HashCode *hash) | ||
927 | { | ||
928 | struct GNUNET_CRYPTO_RsaPublicKey *pkey; | ||
929 | gcry_mpi_t v = NULL; | ||
930 | struct GNUNET_CRYPTO_RsaSignature *sig; | ||
931 | |||
932 | pkey = GNUNET_CRYPTO_rsa_private_key_get_public (key); | ||
933 | v = rsa_full_domain_hash (pkey, hash); | ||
934 | GNUNET_CRYPTO_rsa_public_key_free (pkey); | ||
935 | if (NULL == v) /* rsa_gcd_validate failed meaning */ | ||
936 | return NULL; /* our *own* RSA key is malicious. */ | ||
937 | |||
938 | sig = rsa_sign_mpi (key, v); | ||
939 | gcry_mpi_release (v); | ||
940 | return sig; | ||
941 | } | ||
942 | |||
943 | |||
944 | void | ||
945 | GNUNET_CRYPTO_rsa_signature_free (struct GNUNET_CRYPTO_RsaSignature *sig) | ||
946 | { | ||
947 | gcry_sexp_release (sig->sexp); | ||
948 | GNUNET_free (sig); | ||
949 | } | ||
950 | |||
951 | |||
952 | size_t | ||
953 | GNUNET_CRYPTO_rsa_signature_encode ( | ||
954 | const struct GNUNET_CRYPTO_RsaSignature *sig, | ||
955 | void **buffer) | ||
956 | { | ||
957 | gcry_mpi_t s; | ||
958 | size_t buf_size; | ||
959 | size_t rsize; | ||
960 | unsigned char *buf; | ||
961 | int ret; | ||
962 | |||
963 | ret = key_from_sexp (&s, | ||
964 | sig->sexp, | ||
965 | "sig-val", | ||
966 | "s"); | ||
967 | if (0 != ret) | ||
968 | ret = key_from_sexp (&s, | ||
969 | sig->sexp, | ||
970 | "rsa", | ||
971 | "s"); | ||
972 | GNUNET_assert (0 == ret); | ||
973 | gcry_mpi_print (GCRYMPI_FMT_USG, | ||
974 | NULL, | ||
975 | 0, | ||
976 | &buf_size, | ||
977 | s); | ||
978 | buf = GNUNET_malloc (buf_size); | ||
979 | GNUNET_assert (0 == | ||
980 | gcry_mpi_print (GCRYMPI_FMT_USG, | ||
981 | buf, | ||
982 | buf_size, | ||
983 | &rsize, | ||
984 | s)); | ||
985 | GNUNET_assert (rsize == buf_size); | ||
986 | *buffer = (void *) buf; | ||
987 | gcry_mpi_release (s); | ||
988 | return buf_size; | ||
989 | } | ||
990 | |||
991 | |||
992 | struct GNUNET_CRYPTO_RsaSignature * | ||
993 | GNUNET_CRYPTO_rsa_signature_decode (const void *buf, | ||
994 | size_t buf_size) | ||
995 | { | ||
996 | struct GNUNET_CRYPTO_RsaSignature *sig; | ||
997 | gcry_mpi_t s; | ||
998 | gcry_sexp_t data; | ||
999 | |||
1000 | if (0 != | ||
1001 | gcry_mpi_scan (&s, | ||
1002 | GCRYMPI_FMT_USG, | ||
1003 | buf, | ||
1004 | buf_size, | ||
1005 | NULL)) | ||
1006 | { | ||
1007 | GNUNET_break_op (0); | ||
1008 | return NULL; | ||
1009 | } | ||
1010 | |||
1011 | if (0 != | ||
1012 | gcry_sexp_build (&data, | ||
1013 | NULL, | ||
1014 | "(sig-val(rsa(s %M)))", | ||
1015 | s)) | ||
1016 | { | ||
1017 | GNUNET_break (0); | ||
1018 | gcry_mpi_release (s); | ||
1019 | return NULL; | ||
1020 | } | ||
1021 | gcry_mpi_release (s); | ||
1022 | sig = GNUNET_new (struct GNUNET_CRYPTO_RsaSignature); | ||
1023 | sig->sexp = data; | ||
1024 | return sig; | ||
1025 | } | ||
1026 | |||
1027 | |||
1028 | struct GNUNET_CRYPTO_RsaPublicKey * | ||
1029 | GNUNET_CRYPTO_rsa_public_key_dup (const struct GNUNET_CRYPTO_RsaPublicKey *key) | ||
1030 | { | ||
1031 | struct GNUNET_CRYPTO_RsaPublicKey *dup; | ||
1032 | gcry_sexp_t dup_sexp; | ||
1033 | size_t erroff; | ||
1034 | |||
1035 | /* check if we really are exporting a public key */ | ||
1036 | dup_sexp = gcry_sexp_find_token (key->sexp, "public-key", 0); | ||
1037 | GNUNET_assert (NULL != dup_sexp); | ||
1038 | gcry_sexp_release (dup_sexp); | ||
1039 | /* copy the sexp */ | ||
1040 | GNUNET_assert (0 == gcry_sexp_build (&dup_sexp, &erroff, "%S", key->sexp)); | ||
1041 | dup = GNUNET_new (struct GNUNET_CRYPTO_RsaPublicKey); | ||
1042 | dup->sexp = dup_sexp; | ||
1043 | return dup; | ||
1044 | } | ||
1045 | |||
1046 | |||
1047 | struct GNUNET_CRYPTO_RsaSignature * | ||
1048 | GNUNET_CRYPTO_rsa_unblind (const struct GNUNET_CRYPTO_RsaSignature *sig, | ||
1049 | const struct GNUNET_CRYPTO_RsaBlindingKeySecret *bks, | ||
1050 | struct GNUNET_CRYPTO_RsaPublicKey *pkey) | ||
1051 | { | ||
1052 | struct RsaBlindingKey *bkey; | ||
1053 | gcry_mpi_t n; | ||
1054 | gcry_mpi_t s; | ||
1055 | gcry_mpi_t r_inv; | ||
1056 | gcry_mpi_t ubsig; | ||
1057 | int ret; | ||
1058 | struct GNUNET_CRYPTO_RsaSignature *sret; | ||
1059 | |||
1060 | BENCHMARK_START (rsa_unblind); | ||
1061 | |||
1062 | ret = key_from_sexp (&n, pkey->sexp, "public-key", "n"); | ||
1063 | if (0 != ret) | ||
1064 | ret = key_from_sexp (&n, pkey->sexp, "rsa", "n"); | ||
1065 | if (0 != ret) | ||
1066 | { | ||
1067 | GNUNET_break_op (0); | ||
1068 | return NULL; | ||
1069 | } | ||
1070 | ret = key_from_sexp (&s, sig->sexp, "sig-val", "s"); | ||
1071 | if (0 != ret) | ||
1072 | ret = key_from_sexp (&s, sig->sexp, "rsa", "s"); | ||
1073 | if (0 != ret) | ||
1074 | { | ||
1075 | gcry_mpi_release (n); | ||
1076 | GNUNET_break_op (0); | ||
1077 | return NULL; | ||
1078 | } | ||
1079 | |||
1080 | bkey = rsa_blinding_key_derive (pkey, bks); | ||
1081 | if (NULL == bkey) | ||
1082 | { | ||
1083 | /* RSA key is malicious since rsa_gcd_validate failed here. | ||
1084 | * It should have failed during GNUNET_CRYPTO_rsa_blind too though, | ||
1085 | * so the exchange is being malicious in an unfamilair way, maybe | ||
1086 | * just trying to crash us. */ | ||
1087 | GNUNET_break_op (0); | ||
1088 | gcry_mpi_release (n); | ||
1089 | gcry_mpi_release (s); | ||
1090 | return NULL; | ||
1091 | } | ||
1092 | |||
1093 | r_inv = gcry_mpi_new (0); | ||
1094 | if (1 != | ||
1095 | gcry_mpi_invm (r_inv, | ||
1096 | bkey->r, | ||
1097 | n)) | ||
1098 | { | ||
1099 | /* We cannot find r mod n, so gcd(r,n) != 1, which should get * | ||
1100 | * caught above, but we handle it the same here. */ | ||
1101 | GNUNET_break_op (0); | ||
1102 | gcry_mpi_release (r_inv); | ||
1103 | rsa_blinding_key_free (bkey); | ||
1104 | gcry_mpi_release (n); | ||
1105 | gcry_mpi_release (s); | ||
1106 | return NULL; | ||
1107 | } | ||
1108 | |||
1109 | ubsig = gcry_mpi_new (0); | ||
1110 | gcry_mpi_mulm (ubsig, s, r_inv, n); | ||
1111 | gcry_mpi_release (n); | ||
1112 | gcry_mpi_release (r_inv); | ||
1113 | gcry_mpi_release (s); | ||
1114 | rsa_blinding_key_free (bkey); | ||
1115 | |||
1116 | sret = GNUNET_new (struct GNUNET_CRYPTO_RsaSignature); | ||
1117 | GNUNET_assert (0 == | ||
1118 | gcry_sexp_build (&sret->sexp, | ||
1119 | NULL, | ||
1120 | "(sig-val (rsa (s %M)))", | ||
1121 | ubsig)); | ||
1122 | gcry_mpi_release (ubsig); | ||
1123 | BENCHMARK_END (rsa_unblind); | ||
1124 | return sret; | ||
1125 | } | ||
1126 | |||
1127 | |||
1128 | enum GNUNET_GenericReturnValue | ||
1129 | GNUNET_CRYPTO_rsa_verify (const struct GNUNET_HashCode *hash, | ||
1130 | const struct GNUNET_CRYPTO_RsaSignature *sig, | ||
1131 | const struct GNUNET_CRYPTO_RsaPublicKey *pkey) | ||
1132 | { | ||
1133 | gcry_sexp_t data; | ||
1134 | gcry_mpi_t r; | ||
1135 | int rc; | ||
1136 | |||
1137 | BENCHMARK_START (rsa_verify); | ||
1138 | |||
1139 | r = rsa_full_domain_hash (pkey, hash); | ||
1140 | if (NULL == r) | ||
1141 | { | ||
1142 | GNUNET_break_op (0); | ||
1143 | /* RSA key is malicious since rsa_gcd_validate failed here. | ||
1144 | * It should have failed during GNUNET_CRYPTO_rsa_blind too though, | ||
1145 | * so the exchange is being malicious in an unfamilair way, maybe | ||
1146 | * just trying to crash us. Arguably, we've only an internal error | ||
1147 | * though because we should've detected this in our previous call | ||
1148 | * to GNUNET_CRYPTO_rsa_unblind. */// | ||
1149 | return GNUNET_NO; | ||
1150 | } | ||
1151 | |||
1152 | data = mpi_to_sexp (r); | ||
1153 | gcry_mpi_release (r); | ||
1154 | |||
1155 | rc = gcry_pk_verify (sig->sexp, | ||
1156 | data, | ||
1157 | pkey->sexp); | ||
1158 | gcry_sexp_release (data); | ||
1159 | if (0 != rc) | ||
1160 | { | ||
1161 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
1162 | _ ("RSA signature verification failed at %s:%d: %s\n"), | ||
1163 | __FILE__, | ||
1164 | __LINE__, | ||
1165 | gcry_strerror (rc)); | ||
1166 | BENCHMARK_END (rsa_verify); | ||
1167 | return GNUNET_SYSERR; | ||
1168 | } | ||
1169 | BENCHMARK_END (rsa_verify); | ||
1170 | return GNUNET_OK; | ||
1171 | } | ||
1172 | |||
1173 | |||
1174 | struct GNUNET_CRYPTO_RsaPrivateKey * | ||
1175 | GNUNET_CRYPTO_rsa_private_key_dup ( | ||
1176 | const struct GNUNET_CRYPTO_RsaPrivateKey *key) | ||
1177 | { | ||
1178 | struct GNUNET_CRYPTO_RsaPrivateKey *dup; | ||
1179 | gcry_sexp_t dup_sexp; | ||
1180 | size_t erroff; | ||
1181 | |||
1182 | /* check if we really are exporting a private key */ | ||
1183 | dup_sexp = gcry_sexp_find_token (key->sexp, "private-key", 0); | ||
1184 | GNUNET_assert (NULL != dup_sexp); | ||
1185 | gcry_sexp_release (dup_sexp); | ||
1186 | /* copy the sexp */ | ||
1187 | GNUNET_assert (0 == gcry_sexp_build (&dup_sexp, &erroff, "%S", key->sexp)); | ||
1188 | dup = GNUNET_new (struct GNUNET_CRYPTO_RsaPrivateKey); | ||
1189 | dup->sexp = dup_sexp; | ||
1190 | return dup; | ||
1191 | } | ||
1192 | |||
1193 | |||
1194 | struct GNUNET_CRYPTO_RsaSignature * | ||
1195 | GNUNET_CRYPTO_rsa_signature_dup (const struct GNUNET_CRYPTO_RsaSignature *sig) | ||
1196 | { | ||
1197 | struct GNUNET_CRYPTO_RsaSignature *dup; | ||
1198 | gcry_sexp_t dup_sexp; | ||
1199 | size_t erroff; | ||
1200 | gcry_mpi_t s; | ||
1201 | int ret; | ||
1202 | |||
1203 | /* verify that this is an RSA signature */ | ||
1204 | ret = key_from_sexp (&s, sig->sexp, "sig-val", "s"); | ||
1205 | if (0 != ret) | ||
1206 | ret = key_from_sexp (&s, sig->sexp, "rsa", "s"); | ||
1207 | GNUNET_assert (0 == ret); | ||
1208 | gcry_mpi_release (s); | ||
1209 | /* copy the sexp */ | ||
1210 | GNUNET_assert (0 == gcry_sexp_build (&dup_sexp, &erroff, "%S", sig->sexp)); | ||
1211 | dup = GNUNET_new (struct GNUNET_CRYPTO_RsaSignature); | ||
1212 | dup->sexp = dup_sexp; | ||
1213 | return dup; | ||
1214 | } | ||
1215 | |||
1216 | |||
1217 | /* end of util/rsa.c */ | ||