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