aboutsummaryrefslogtreecommitdiff
path: root/src/lib/util/crypto_rsa.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/util/crypto_rsa.c')
-rw-r--r--src/lib/util/crypto_rsa.c1290
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 */
40struct 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 */
52struct 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 */
64struct 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 */
76struct 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 */
94static int
95key_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
143struct GNUNET_CRYPTO_RsaPrivateKey *
144GNUNET_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
172void
173GNUNET_CRYPTO_rsa_private_key_free (struct GNUNET_CRYPTO_RsaPrivateKey *key)
174{
175 gcry_sexp_release (key->sexp);
176 GNUNET_free (key);
177}
178
179
180size_t
181GNUNET_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
203struct GNUNET_CRYPTO_RsaPrivateKey *
204GNUNET_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
232struct GNUNET_CRYPTO_RsaPublicKey *
233GNUNET_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
267void
268GNUNET_CRYPTO_rsa_public_key_free (struct GNUNET_CRYPTO_RsaPublicKey *key)
269{
270 gcry_sexp_release (key->sexp);
271 GNUNET_free (key);
272}
273
274
275GNUNET_NETWORK_STRUCT_BEGIN
276
277/**
278 * Format of the header of a serialized RSA public key.
279 */
280struct 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
297GNUNET_NETWORK_STRUCT_END
298
299
300bool
301GNUNET_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
324size_t
325GNUNET_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
406void
407GNUNET_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
422struct GNUNET_CRYPTO_RsaPublicKey *
423GNUNET_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 */
500static int
501rsa_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 */
521static struct RsaBlindingKey *
522rsa_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
601int
602GNUNET_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
627int
628GNUNET_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
653int
654GNUNET_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
679unsigned int
680GNUNET_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 */
701static void
702rsa_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 */
716static size_t
717numeric_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 */
754static gcry_mpi_t
755rsa_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
798void
799GNUNET_CRYPTO_rsa_blinded_message_free (
800 struct GNUNET_CRYPTO_RsaBlindedMessage *bm)
801{
802 GNUNET_free (bm->blinded_msg);
803}
804
805
806enum GNUNET_GenericReturnValue
807GNUNET_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
875rsa_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 */
893static gcry_sexp_t
894mpi_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 */
914static struct GNUNET_CRYPTO_RsaSignature *
915rsa_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
969struct GNUNET_CRYPTO_RsaSignature *
970GNUNET_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
991struct GNUNET_CRYPTO_RsaSignature *
992GNUNET_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
1014void
1015GNUNET_CRYPTO_rsa_signature_free (struct GNUNET_CRYPTO_RsaSignature *sig)
1016{
1017 gcry_sexp_release (sig->sexp);
1018 GNUNET_free (sig);
1019}
1020
1021
1022size_t
1023GNUNET_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
1062struct GNUNET_CRYPTO_RsaSignature *
1063GNUNET_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
1098struct GNUNET_CRYPTO_RsaPublicKey *
1099GNUNET_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
1117struct GNUNET_CRYPTO_RsaSignature *
1118GNUNET_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
1198enum GNUNET_GenericReturnValue
1199GNUNET_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
1247struct GNUNET_CRYPTO_RsaPrivateKey *
1248GNUNET_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
1267struct GNUNET_CRYPTO_RsaSignature *
1268GNUNET_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 */