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.c1217
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 */
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
299size_t
300GNUNET_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
366void
367GNUNET_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
382struct GNUNET_CRYPTO_RsaPublicKey *
383GNUNET_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 */
460static int
461rsa_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 */
480static struct RsaBlindingKey *
481rsa_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
555int
556GNUNET_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
581int
582GNUNET_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
607int
608GNUNET_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
633unsigned int
634GNUNET_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 */
655static void
656rsa_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 */
670static size_t
671numeric_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 */
707static gcry_mpi_t
708rsa_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
743enum GNUNET_GenericReturnValue
744GNUNET_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
807rsa_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 */
824static gcry_sexp_t
825mpi_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 */
845static struct GNUNET_CRYPTO_RsaSignature *
846rsa_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
900struct GNUNET_CRYPTO_RsaSignature *
901GNUNET_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
924struct GNUNET_CRYPTO_RsaSignature *
925GNUNET_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
944void
945GNUNET_CRYPTO_rsa_signature_free (struct GNUNET_CRYPTO_RsaSignature *sig)
946{
947 gcry_sexp_release (sig->sexp);
948 GNUNET_free (sig);
949}
950
951
952size_t
953GNUNET_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
992struct GNUNET_CRYPTO_RsaSignature *
993GNUNET_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
1028struct GNUNET_CRYPTO_RsaPublicKey *
1029GNUNET_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
1047struct GNUNET_CRYPTO_RsaSignature *
1048GNUNET_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
1128enum GNUNET_GenericReturnValue
1129GNUNET_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
1174struct GNUNET_CRYPTO_RsaPrivateKey *
1175GNUNET_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
1194struct GNUNET_CRYPTO_RsaSignature *
1195GNUNET_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 */