GNUnet  0.17.6
crypto_rsa.c
Go to the documentation of this file.
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 
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 
40 {
44  gcry_sexp_t sexp;
45 };
46 
47 
52 {
56  gcry_sexp_t sexp;
57 };
58 
59 
64 {
68  gcry_sexp_t sexp;
69 };
70 
71 
76 {
80  gcry_mpi_t r;
81 };
82 
83 
93 static int
94 key_from_sexp (gcry_mpi_t *array,
95  gcry_sexp_t sexp,
96  const char *topname,
97  const char *elems)
98 {
99  gcry_sexp_t list;
100  gcry_sexp_t l2;
101  const char *s;
102  unsigned int idx;
103 
104  if (! (list = gcry_sexp_find_token (sexp, topname, 0)))
105  return 1;
106  l2 = gcry_sexp_cadr (list);
107  gcry_sexp_release (list);
108  list = l2;
109  if (! list)
110  return 2;
111  idx = 0;
112  for (s = elems; *s; s++, idx++)
113  {
114  if (! (l2 = gcry_sexp_find_token (list, s, 1)))
115  {
116  for (unsigned int i = 0; i < idx; i++)
117  {
118  gcry_free (array[i]);
119  array[i] = NULL;
120  }
121  gcry_sexp_release (list);
122  return 3; /* required parameter not found */
123  }
124  array[idx] = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
125  gcry_sexp_release (l2);
126  if (! array[idx])
127  {
128  for (unsigned int i = 0; i < idx; i++)
129  {
130  gcry_free (array[i]);
131  array[i] = NULL;
132  }
133  gcry_sexp_release (list);
134  return 4; /* required parameter is invalid */
135  }
136  }
137  gcry_sexp_release (list);
138  return 0;
139 }
140 
141 
144 {
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
165  ret->sexp = s_key;
166  BENCHMARK_END (rsa_private_key_create);
167  return ret;
168 }
169 
170 
171 void
173 {
174  gcry_sexp_release (key->sexp);
175  GNUNET_free (key);
176 }
177 
178 
179 size_t
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 
204  size_t buf_size)
205 {
207 
209  if (0 !=
210  gcry_sexp_new (&key->sexp,
211  buf,
212  buf_size,
213  0))
214  {
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  {
223  "Decoded private key is not valid\n");
225  return NULL;
226  }
227  return key;
228 }
229 
230 
233  const struct GNUNET_CRYPTO_RsaPrivateKey *priv)
234 {
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]);
260  pub->sexp = result;
261  BENCHMARK_END (rsa_private_key_get_public);
262  return pub;
263 }
264 
265 
266 void
268 {
269  gcry_sexp_release (key->sexp);
270  GNUNET_free (key);
271 }
272 
273 
275 
280 {
285 
290 
291  /* followed by variable-size modulus and
292  public exponent follows as big-endian encoded
293  integers */
294 };
295 
297 
298 
299 bool
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 
323 size_t
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;
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 
405 void
407  struct GNUNET_HashCode *hc)
408 {
409  void *buf;
410  size_t buf_size;
411 
413  &buf);
415  buf_size,
416  hc);
417  GNUNET_free (buf);
418 }
419 
420 
423  size_t len)
424 {
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);
483  key->sexp = data;
484  return key;
485 }
486 
487 
499 static int
500 rsa_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 
520 static struct RsaBlindingKey *
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 
600 int
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 
611  &b1);
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 
626 int
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 
637  &b1);
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 
652 int
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 
663  &b1);
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 
678 unsigned int
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 
700 static void
702 {
703  gcry_mpi_release (bkey->r);
704  GNUNET_free (bkey);
705 }
706 
707 
715 static size_t
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 
752 static gcry_mpi_t
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! */
771  &xts);
772 
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 
789 GNUNET_CRYPTO_rsa_blind (const struct GNUNET_HashCode *hash,
790  const struct GNUNET_CRYPTO_RsaBlindingKeySecret *bks,
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 
852 rsa_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 
869 static gcry_sexp_t
870 mpi_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 
890 static struct GNUNET_CRYPTO_RsaSignature *
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  {
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 =
923  if (0 !=
924  gcry_pk_verify (result,
925  data,
926  public_key->sexp))
927  {
928  GNUNET_break (0);
930  gcry_sexp_release (data);
931  gcry_sexp_release (result);
932  return NULL;
933  }
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 
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 
971  const struct GNUNET_HashCode *hash)
972 {
974  gcry_mpi_t v = NULL;
975  struct GNUNET_CRYPTO_RsaSignature *sig;
976 
978  v = rsa_full_domain_hash (pkey, hash);
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 
989 void
991 {
992  gcry_sexp_release (sig->sexp);
993  GNUNET_free (sig);
994 }
995 
996 
997 size_t
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 
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 
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 
1094  const struct GNUNET_CRYPTO_RsaBlindingKeySecret *bks,
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 
1174 GNUNET_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  {
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 
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 
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 */
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
benchmarking for various operations
#define BENCHMARK_START(opname)
Definition: benchmark.h:57
#define BENCHMARK_END(opname)
Definition: benchmark.h:58
static int key_from_sexp(gcry_mpi_t *array, gcry_sexp_t sexp, const char *topname, const char *elems)
Extract values from an S-expression.
Definition: crypto_rsa.c:94
static void rsa_blinding_key_free(struct RsaBlindingKey *bkey)
Destroy a blinding key.
Definition: crypto_rsa.c:701
static gcry_sexp_t mpi_to_sexp(gcry_mpi_t value)
Convert an MPI to an S-expression suitable for signature operations.
Definition: crypto_rsa.c:870
static struct GNUNET_CRYPTO_RsaSignature * rsa_sign_mpi(const struct GNUNET_CRYPTO_RsaPrivateKey *key, gcry_mpi_t value)
Sign the given MPI.
Definition: crypto_rsa.c:891
static gcry_mpi_t rsa_full_domain_hash(const struct GNUNET_CRYPTO_RsaPublicKey *pkey, const struct GNUNET_HashCode *hash)
Computes a full domain hash seeded by the given public key.
Definition: crypto_rsa.c:753
static struct RsaBlindingKey * rsa_blinding_key_derive(const struct GNUNET_CRYPTO_RsaPublicKey *pkey, const struct GNUNET_CRYPTO_RsaBlindingKeySecret *bks)
Create a blinding key.
Definition: crypto_rsa.c:521
#define LOG(kind,...)
Definition: crypto_rsa.c:33
static int rsa_gcd_validate(gcry_mpi_t r, gcry_mpi_t n)
Test for malicious RSA key.
Definition: crypto_rsa.c:500
static size_t numeric_mpi_alloc_n_print(gcry_mpi_t v, char **buffer)
Print an MPI to a newly created buffer.
Definition: crypto_rsa.c:716
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
static int list
Set if we should print a list of currently running services.
Definition: gnunet-arm.c:69
static struct Experiment * e
struct GNUNET_HashCode key
The key used in the DHT.
uint32_t data
The data value.
uint16_t len
length of data (which is always a uint32_t, but presumably this can be used to specify that fewer byt...
static char * pkey
Public key of the zone to look in, in ASCII.
static char * value
Value of the record to add/remove.
static int ok
Return value from 'main' (0 == success)
static int result
Global testing status.
static struct GNUNET_CRYPTO_EddsaPublicKey pub
Definition: gnunet-scrypt.c:46
static char buf[2048]
static struct GNUNET_SCHEDULER_Task * t
Main task.
cryptographic primitives for GNUnet
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition: crypto_hash.c:41
struct GNUNET_CRYPTO_RsaPublicKey * GNUNET_CRYPTO_rsa_public_key_dup(const struct GNUNET_CRYPTO_RsaPublicKey *key)
Duplicate the given public key.
Definition: crypto_rsa.c:1074
#define GNUNET_NETWORK_STRUCT_BEGIN
Define as empty, GNUNET_PACKED should suffice, but this won't work on W32.
struct GNUNET_CRYPTO_RsaSignature * GNUNET_CRYPTO_rsa_signature_decode(const void *buf, size_t buf_size)
Decode the signature from the data-format back to the "normal", internal format.
Definition: crypto_rsa.c:1038
void GNUNET_CRYPTO_rsa_signature_free(struct GNUNET_CRYPTO_RsaSignature *sig)
Free memory occupied by signature.
Definition: crypto_rsa.c:990
void GNUNET_CRYPTO_rsa_private_key_free(struct GNUNET_CRYPTO_RsaPrivateKey *key)
Free memory occupied by the private key.
Definition: crypto_rsa.c:172
void GNUNET_CRYPTO_kdf_mod_mpi(gcry_mpi_t *r, gcry_mpi_t n, const void *xts, size_t xts_len, const void *skm, size_t skm_len, const char *ctx)
Deterministically generate a pseudo-random number uniformly from the integers modulo a libgcrypt mpi.
Definition: crypto_kdf.c:94
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_rsa_verify(const struct GNUNET_HashCode *hash, const struct GNUNET_CRYPTO_RsaSignature *sig, const struct GNUNET_CRYPTO_RsaPublicKey *pkey)
Verify whether the given hash corresponds to the given signature and the signature is valid with resp...
Definition: crypto_rsa.c:1174
struct GNUNET_CRYPTO_RsaPrivateKey * GNUNET_CRYPTO_rsa_private_key_decode(const void *buf, size_t buf_size)
Decode the private key from the data-format back to the "normal", internal format.
Definition: crypto_rsa.c:203
struct GNUNET_CRYPTO_RsaSignature * GNUNET_CRYPTO_rsa_unblind(const struct GNUNET_CRYPTO_RsaSignature *sig, const struct GNUNET_CRYPTO_RsaBlindingKeySecret *bks, struct GNUNET_CRYPTO_RsaPublicKey *pkey)
Unblind a blind-signed signature.
Definition: crypto_rsa.c:1093
int GNUNET_CRYPTO_rsa_signature_cmp(const struct GNUNET_CRYPTO_RsaSignature *s1, const struct GNUNET_CRYPTO_RsaSignature *s2)
Compare the values of two signatures.
Definition: crypto_rsa.c:601
GNUNET_NETWORK_STRUCT_END bool GNUNET_CRYPTO_rsa_public_key_check(const struct GNUNET_CRYPTO_RsaPublicKey *key)
Check if key is well-formed.
Definition: crypto_rsa.c:300
unsigned int GNUNET_CRYPTO_rsa_public_key_len(const struct GNUNET_CRYPTO_RsaPublicKey *key)
Obtain the length of the RSA key in bits.
Definition: crypto_rsa.c:679
void GNUNET_CRYPTO_rsa_public_key_hash(const struct GNUNET_CRYPTO_RsaPublicKey *key, struct GNUNET_HashCode *hc)
Compute hash over the public key.
Definition: crypto_rsa.c:406
void GNUNET_CRYPTO_rsa_public_key_free(struct GNUNET_CRYPTO_RsaPublicKey *key)
Free memory occupied by the public key.
Definition: crypto_rsa.c:267
struct GNUNET_CRYPTO_RsaPublicKey * GNUNET_CRYPTO_rsa_public_key_decode(const char *buf, size_t len)
Decode the public key from the data-format back to the "normal", internal format.
Definition: crypto_rsa.c:422
#define GNUNET_NETWORK_STRUCT_END
Define as empty, GNUNET_PACKED should suffice, but this won't work on W32;.
size_t GNUNET_CRYPTO_rsa_public_key_encode(const struct GNUNET_CRYPTO_RsaPublicKey *key, void **buffer)
Encode the public key in a format suitable for storing it into a file.
Definition: crypto_rsa.c:324
int GNUNET_CRYPTO_rsa_private_key_cmp(const struct GNUNET_CRYPTO_RsaPrivateKey *p1, const struct GNUNET_CRYPTO_RsaPrivateKey *p2)
Compare the values of two private keys.
Definition: crypto_rsa.c:653
size_t GNUNET_CRYPTO_rsa_signature_encode(const struct GNUNET_CRYPTO_RsaSignature *sig, void **buffer)
Encode the given signature in a format suitable for storing it into a file.
Definition: crypto_rsa.c:998
struct GNUNET_CRYPTO_RsaSignature * GNUNET_CRYPTO_rsa_signature_dup(const struct GNUNET_CRYPTO_RsaSignature *sig)
Duplicate the given rsa signature.
Definition: crypto_rsa.c:1240
struct GNUNET_CRYPTO_RsaSignature * GNUNET_CRYPTO_rsa_sign_fdh(const struct GNUNET_CRYPTO_RsaPrivateKey *key, const struct GNUNET_HashCode *hash)
Create and sign a full domain hash of a message.
Definition: crypto_rsa.c:970
int GNUNET_CRYPTO_rsa_public_key_cmp(const struct GNUNET_CRYPTO_RsaPublicKey *p1, const struct GNUNET_CRYPTO_RsaPublicKey *p2)
Compare the values of two public keys.
Definition: crypto_rsa.c:627
struct GNUNET_CRYPTO_RsaPublicKey * GNUNET_CRYPTO_rsa_private_key_get_public(const struct GNUNET_CRYPTO_RsaPrivateKey *priv)
Extract the public key of the given private key.
Definition: crypto_rsa.c:232
GNUNET_GenericReturnValue
Named constants for return values.
Definition: gnunet_common.h:96
size_t GNUNET_CRYPTO_rsa_private_key_encode(const struct GNUNET_CRYPTO_RsaPrivateKey *key, void **buffer)
Encode the private key in a format suitable for storing it into a file.
Definition: crypto_rsa.c:180
struct GNUNET_CRYPTO_RsaPrivateKey * GNUNET_CRYPTO_rsa_private_key_create(unsigned int len)
Create a new private key.
Definition: crypto_rsa.c:143
struct GNUNET_CRYPTO_RsaPrivateKey * GNUNET_CRYPTO_rsa_private_key_dup(const struct GNUNET_CRYPTO_RsaPrivateKey *key)
Duplicate the given private key.
Definition: crypto_rsa.c:1220
#define GNUNET_PACKED
gcc-ism to get packed structs.
struct GNUNET_CRYPTO_RsaSignature * GNUNET_CRYPTO_rsa_sign_blinded(const struct GNUNET_CRYPTO_RsaPrivateKey *key, const void *msg, size_t msg_len)
Sign a blinded value, which must be a full domain hash of a message.
Definition: crypto_rsa.c:946
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_rsa_blind(const struct GNUNET_HashCode *hash, const struct GNUNET_CRYPTO_RsaBlindingKeySecret *bks, struct GNUNET_CRYPTO_RsaPublicKey *pkey, void **buf, size_t *buf_size)
Blinds the given message with the given blinding key.
Definition: crypto_rsa.c:789
@ GNUNET_OK
Definition: gnunet_common.h:99
@ GNUNET_YES
@ GNUNET_NO
Definition: gnunet_common.h:98
@ GNUNET_SYSERR
Definition: gnunet_common.h:97
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
@ GNUNET_ERROR_TYPE_WARNING
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_free(ptr)
Wrapper around free.
#define _(String)
GNU gettext support macro.
Definition: platform.h:177
Constant-size pre-secret for blinding key generation.
The private information of an RSA key pair.
Definition: crypto_rsa.c:40
gcry_sexp_t sexp
Libgcrypt S-expression for the RSA private key.
Definition: crypto_rsa.c:44
Format of the header of a serialized RSA public key.
Definition: crypto_rsa.c:280
uint16_t public_exponent_length
length of exponent in bytes, in NBO
Definition: crypto_rsa.c:289
uint16_t modulus_length
length of modulus 'n' in bytes, in NBO
Definition: crypto_rsa.c:284
The public information of an RSA key pair.
Definition: crypto_rsa.c:52
gcry_sexp_t sexp
Libgcrypt S-expression for the RSA public key.
Definition: crypto_rsa.c:56
an RSA signature
Definition: crypto_rsa.c:64
gcry_sexp_t sexp
Libgcrypt S-expression for the RSA signature.
Definition: crypto_rsa.c:68
A 512-bit hashcode.
RSA blinding key.
Definition: crypto_rsa.c:76
gcry_mpi_t r
Random value used for blinding.
Definition: crypto_rsa.c:80