GNUnet  0.19.3
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 
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 
41 {
45  gcry_sexp_t sexp;
46 };
47 
48 
53 {
57  gcry_sexp_t sexp;
58 };
59 
60 
65 {
69  gcry_sexp_t sexp;
70 };
71 
72 
77 {
81  gcry_mpi_t r;
82 };
83 
84 
94 static int
95 key_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 
145 {
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
166  ret->sexp = s_key;
167  BENCHMARK_END (rsa_private_key_create);
168  return ret;
169 }
170 
171 
172 void
174 {
175  gcry_sexp_release (key->sexp);
176  GNUNET_free (key);
177 }
178 
179 
180 size_t
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 
205  size_t buf_size)
206 {
208 
210  if (0 !=
211  gcry_sexp_new (&key->sexp,
212  buf,
213  buf_size,
214  0))
215  {
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  {
224  "Decoded private key is not valid\n");
226  return NULL;
227  }
228  return key;
229 }
230 
231 
234  const struct GNUNET_CRYPTO_RsaPrivateKey *priv)
235 {
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]);
261  pub->sexp = result;
262  BENCHMARK_END (rsa_private_key_get_public);
263  return pub;
264 }
265 
266 
267 void
269 {
270  gcry_sexp_release (key->sexp);
271  GNUNET_free (key);
272 }
273 
274 
276 
281 {
286 
291 
292  /* followed by variable-size modulus and
293  public exponent follows as big-endian encoded
294  integers */
295 };
296 
298 
299 
300 bool
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 
324 size_t
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;
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 
406 void
408  struct GNUNET_HashCode *hc)
409 {
410  void *buf;
411  size_t buf_size;
412 
414  &buf);
416  buf_size,
417  hc);
418  GNUNET_free (buf);
419 }
420 
421 
424  size_t len)
425 {
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);
484  key->sexp = data;
485  return key;
486 }
487 
488 
500 static int
501 rsa_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 
521 static struct RsaBlindingKey *
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 
601 int
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 
612  &b1);
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 
627 int
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 
638  &b1);
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 
653 int
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 
664  &b1);
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 
679 unsigned int
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 
701 static void
703 {
704  gcry_mpi_release (bkey->r);
705  GNUNET_free (bkey);
706 }
707 
708 
716 static size_t
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 
753 static gcry_mpi_t
755  const struct GNUNET_HashCode *hash)
756 {
757  gcry_mpi_t r, n;
758  void *xts;
759  size_t xts_len;
760  int ok;
761 
762  /* Extract the composite n from the RSA public key */
763  GNUNET_assert (0 == key_from_sexp (&n, pkey->sexp, "rsa", "n"));
764  /* Assert that it at least looks like an RSA key */
765  GNUNET_assert (0 == gcry_mpi_get_flag (n, GCRYMPI_FLAG_OPAQUE));
766 
767  /* We key with the public denomination key as a homage to RSA-PSS by *
768  * Mihir Bellare and Phillip Rogaway. Doing this lowers the degree *
769  * of the hypothetical polyomial-time attack on RSA-KTI created by a *
770  * polynomial-time one-more forgary attack. Yey seeding! */
772  &xts);
773 
775  n,
776  xts, xts_len,
777  hash, sizeof(*hash),
778  "RSA-FDA FTpsW!");
779  GNUNET_free (xts);
780  ok = rsa_gcd_validate (r, n);
781  gcry_mpi_release (n);
782  if (ok)
783  return r;
784  gcry_mpi_release (r);
785  return NULL;
786 }
787 
788 
790 GNUNET_CRYPTO_rsa_blind (const struct GNUNET_HashCode *hash,
791  const struct GNUNET_CRYPTO_RsaBlindingKeySecret *bks,
793  void **buf,
794  size_t *buf_size)
795 {
796  struct RsaBlindingKey *bkey;
797  gcry_mpi_t data;
798  gcry_mpi_t ne[2];
799  gcry_mpi_t r_e;
800  gcry_mpi_t data_r_e;
801  int ret;
802 
803  BENCHMARK_START (rsa_blind);
804 
805  GNUNET_assert (buf != NULL);
806  GNUNET_assert (buf_size != NULL);
807  ret = key_from_sexp (ne, pkey->sexp, "public-key", "ne");
808  if (0 != ret)
809  ret = key_from_sexp (ne, pkey->sexp, "rsa", "ne");
810  if (0 != ret)
811  {
812  GNUNET_break (0);
813  *buf = NULL;
814  *buf_size = 0;
815  return GNUNET_NO;
816  }
817 
818  data = rsa_full_domain_hash (pkey, hash);
819  if (NULL == data)
820  goto rsa_gcd_validate_failure;
821 
822  bkey = rsa_blinding_key_derive (pkey, bks);
823  if (NULL == bkey)
824  {
825  gcry_mpi_release (data);
826  goto rsa_gcd_validate_failure;
827  }
828 
829  r_e = gcry_mpi_new (0);
830  gcry_mpi_powm (r_e,
831  bkey->r,
832  ne[1],
833  ne[0]);
834  data_r_e = gcry_mpi_new (0);
835  gcry_mpi_mulm (data_r_e,
836  data,
837  r_e,
838  ne[0]);
839  gcry_mpi_release (data);
840  gcry_mpi_release (ne[0]);
841  gcry_mpi_release (ne[1]);
842  gcry_mpi_release (r_e);
843  rsa_blinding_key_free (bkey);
844 
845  *buf_size = numeric_mpi_alloc_n_print (data_r_e,
846  (char **) buf);
847  gcry_mpi_release (data_r_e);
848 
849  BENCHMARK_END (rsa_blind);
850 
851  return GNUNET_YES;
852 
853 rsa_gcd_validate_failure:
854  /* We know the RSA key is malicious here, so warn the wallet. */
855  /* GNUNET_break_op (0); */
856  gcry_mpi_release (ne[0]);
857  gcry_mpi_release (ne[1]);
858  *buf = NULL;
859  *buf_size = 0;
860  return GNUNET_NO;
861 }
862 
863 
870 static gcry_sexp_t
871 mpi_to_sexp (gcry_mpi_t value)
872 {
873  gcry_sexp_t data = NULL;
874 
875  GNUNET_assert (0 ==
876  gcry_sexp_build (&data,
877  NULL,
878  "(data (flags raw) (value %M))",
879  value));
880  return data;
881 }
882 
883 
891 static struct GNUNET_CRYPTO_RsaSignature *
893  gcry_mpi_t value)
894 {
895  struct GNUNET_CRYPTO_RsaSignature *sig;
896  gcry_sexp_t data;
897  gcry_sexp_t result;
898  int rc;
899 
900  data = mpi_to_sexp (value);
901 
902  if (0 !=
903  (rc = gcry_pk_sign (&result,
904  data,
905  key->sexp)))
906  {
908  _ ("RSA signing failed at %s:%d: %s\n"),
909  __FILE__,
910  __LINE__,
911  gcry_strerror (rc));
912  gcry_sexp_release (data);
913  GNUNET_break (0);
914  return NULL;
915  }
916 
917  /* Lenstra protection was first added to libgcrypt 1.6.4
918  * with commit c17f84bd02d7ee93845e92e20f6ddba814961588.
919  */
920 #if GCRYPT_VERSION_NUMBER < 0x010604
921  /* verify signature (guards against Lenstra's attack with fault injection...) */
922  struct GNUNET_CRYPTO_RsaPublicKey *public_key =
924  if (0 !=
925  gcry_pk_verify (result,
926  data,
927  public_key->sexp))
928  {
929  GNUNET_break (0);
931  gcry_sexp_release (data);
932  gcry_sexp_release (result);
933  return NULL;
934  }
936 #endif
937 
938  /* return signature */
939  gcry_sexp_release (data);
940  sig = GNUNET_new (struct GNUNET_CRYPTO_RsaSignature);
941  sig->sexp = result;
942  return sig;
943 }
944 
945 
948  const void *msg,
949  size_t msg_len)
950 {
951  gcry_mpi_t v = NULL;
952  struct GNUNET_CRYPTO_RsaSignature *sig;
953 
954  BENCHMARK_START (rsa_sign_blinded);
955 
956  GNUNET_assert (0 ==
957  gcry_mpi_scan (&v,
958  GCRYMPI_FMT_USG,
959  msg,
960  msg_len,
961  NULL));
962 
963  sig = rsa_sign_mpi (key, v);
964  gcry_mpi_release (v);
965  BENCHMARK_END (rsa_sign_blinded);
966  return sig;
967 }
968 
969 
972  const struct GNUNET_HashCode *hash)
973 {
975  gcry_mpi_t v = NULL;
976  struct GNUNET_CRYPTO_RsaSignature *sig;
977 
979  v = rsa_full_domain_hash (pkey, hash);
981  if (NULL == v) /* rsa_gcd_validate failed meaning */
982  return NULL; /* our *own* RSA key is malicious. */
983 
984  sig = rsa_sign_mpi (key, v);
985  gcry_mpi_release (v);
986  return sig;
987 }
988 
989 
990 void
992 {
993  gcry_sexp_release (sig->sexp);
994  GNUNET_free (sig);
995 }
996 
997 
998 size_t
1000  const struct GNUNET_CRYPTO_RsaSignature *sig,
1001  void **buffer)
1002 {
1003  gcry_mpi_t s;
1004  size_t buf_size;
1005  size_t rsize;
1006  unsigned char *buf;
1007  int ret;
1008 
1009  ret = key_from_sexp (&s,
1010  sig->sexp,
1011  "sig-val",
1012  "s");
1013  if (0 != ret)
1014  ret = key_from_sexp (&s,
1015  sig->sexp,
1016  "rsa",
1017  "s");
1018  GNUNET_assert (0 == ret);
1019  gcry_mpi_print (GCRYMPI_FMT_USG,
1020  NULL,
1021  0,
1022  &buf_size,
1023  s);
1024  buf = GNUNET_malloc (buf_size);
1025  GNUNET_assert (0 ==
1026  gcry_mpi_print (GCRYMPI_FMT_USG,
1027  buf,
1028  buf_size,
1029  &rsize,
1030  s));
1031  GNUNET_assert (rsize == buf_size);
1032  *buffer = (void *) buf;
1033  gcry_mpi_release (s);
1034  return buf_size;
1035 }
1036 
1037 
1040  size_t buf_size)
1041 {
1042  struct GNUNET_CRYPTO_RsaSignature *sig;
1043  gcry_mpi_t s;
1044  gcry_sexp_t data;
1045 
1046  if (0 !=
1047  gcry_mpi_scan (&s,
1048  GCRYMPI_FMT_USG,
1049  buf,
1050  buf_size,
1051  NULL))
1052  {
1053  GNUNET_break_op (0);
1054  return NULL;
1055  }
1056 
1057  if (0 !=
1058  gcry_sexp_build (&data,
1059  NULL,
1060  "(sig-val(rsa(s %M)))",
1061  s))
1062  {
1063  GNUNET_break (0);
1064  gcry_mpi_release (s);
1065  return NULL;
1066  }
1067  gcry_mpi_release (s);
1068  sig = GNUNET_new (struct GNUNET_CRYPTO_RsaSignature);
1069  sig->sexp = data;
1070  return sig;
1071 }
1072 
1073 
1076 {
1077  struct GNUNET_CRYPTO_RsaPublicKey *dup;
1078  gcry_sexp_t dup_sexp;
1079  size_t erroff;
1080 
1081  /* check if we really are exporting a public key */
1082  dup_sexp = gcry_sexp_find_token (key->sexp, "public-key", 0);
1083  GNUNET_assert (NULL != dup_sexp);
1084  gcry_sexp_release (dup_sexp);
1085  /* copy the sexp */
1086  GNUNET_assert (0 == gcry_sexp_build (&dup_sexp, &erroff, "%S", key->sexp));
1087  dup = GNUNET_new (struct GNUNET_CRYPTO_RsaPublicKey);
1088  dup->sexp = dup_sexp;
1089  return dup;
1090 }
1091 
1092 
1095  const struct GNUNET_CRYPTO_RsaBlindingKeySecret *bks,
1097 {
1098  struct RsaBlindingKey *bkey;
1099  gcry_mpi_t n;
1100  gcry_mpi_t s;
1101  gcry_mpi_t r_inv;
1102  gcry_mpi_t ubsig;
1103  int ret;
1104  struct GNUNET_CRYPTO_RsaSignature *sret;
1105 
1106  BENCHMARK_START (rsa_unblind);
1107 
1108  ret = key_from_sexp (&n, pkey->sexp, "public-key", "n");
1109  if (0 != ret)
1110  ret = key_from_sexp (&n, pkey->sexp, "rsa", "n");
1111  if (0 != ret)
1112  {
1113  GNUNET_break_op (0);
1114  return NULL;
1115  }
1116  ret = key_from_sexp (&s, sig->sexp, "sig-val", "s");
1117  if (0 != ret)
1118  ret = key_from_sexp (&s, sig->sexp, "rsa", "s");
1119  if (0 != ret)
1120  {
1121  gcry_mpi_release (n);
1122  GNUNET_break_op (0);
1123  return NULL;
1124  }
1125 
1126  bkey = rsa_blinding_key_derive (pkey, bks);
1127  if (NULL == bkey)
1128  {
1129  /* RSA key is malicious since rsa_gcd_validate failed here.
1130  * It should have failed during GNUNET_CRYPTO_rsa_blind too though,
1131  * so the exchange is being malicious in an unfamilair way, maybe
1132  * just trying to crash us. */
1133  GNUNET_break_op (0);
1134  gcry_mpi_release (n);
1135  gcry_mpi_release (s);
1136  return NULL;
1137  }
1138 
1139  r_inv = gcry_mpi_new (0);
1140  if (1 !=
1141  gcry_mpi_invm (r_inv,
1142  bkey->r,
1143  n))
1144  {
1145  /* We cannot find r mod n, so gcd(r,n) != 1, which should get *
1146  * caught above, but we handle it the same here. */
1147  GNUNET_break_op (0);
1148  gcry_mpi_release (r_inv);
1149  rsa_blinding_key_free (bkey);
1150  gcry_mpi_release (n);
1151  gcry_mpi_release (s);
1152  return NULL;
1153  }
1154 
1155  ubsig = gcry_mpi_new (0);
1156  gcry_mpi_mulm (ubsig, s, r_inv, n);
1157  gcry_mpi_release (n);
1158  gcry_mpi_release (r_inv);
1159  gcry_mpi_release (s);
1160  rsa_blinding_key_free (bkey);
1161 
1162  sret = GNUNET_new (struct GNUNET_CRYPTO_RsaSignature);
1163  GNUNET_assert (0 ==
1164  gcry_sexp_build (&sret->sexp,
1165  NULL,
1166  "(sig-val (rsa (s %M)))",
1167  ubsig));
1168  gcry_mpi_release (ubsig);
1169  BENCHMARK_END (rsa_unblind);
1170  return sret;
1171 }
1172 
1173 
1175 GNUNET_CRYPTO_rsa_verify (const struct GNUNET_HashCode *hash,
1176  const struct GNUNET_CRYPTO_RsaSignature *sig,
1177  const struct GNUNET_CRYPTO_RsaPublicKey *pkey)
1178 {
1179  gcry_sexp_t data;
1180  gcry_mpi_t r;
1181  int rc;
1182 
1183  BENCHMARK_START (rsa_verify);
1184 
1185  r = rsa_full_domain_hash (pkey, hash);
1186  if (NULL == r)
1187  {
1188  GNUNET_break_op (0);
1189  /* RSA key is malicious since rsa_gcd_validate failed here.
1190  * It should have failed during GNUNET_CRYPTO_rsa_blind too though,
1191  * so the exchange is being malicious in an unfamilair way, maybe
1192  * just trying to crash us. Arguably, we've only an internal error
1193  * though because we should've detected this in our previous call
1194  * to GNUNET_CRYPTO_rsa_unblind. *///
1195  return GNUNET_NO;
1196  }
1197 
1198  data = mpi_to_sexp (r);
1199  gcry_mpi_release (r);
1200 
1201  rc = gcry_pk_verify (sig->sexp,
1202  data,
1203  pkey->sexp);
1204  gcry_sexp_release (data);
1205  if (0 != rc)
1206  {
1208  _ ("RSA signature verification failed at %s:%d: %s\n"),
1209  __FILE__,
1210  __LINE__,
1211  gcry_strerror (rc));
1212  BENCHMARK_END (rsa_verify);
1213  return GNUNET_SYSERR;
1214  }
1215  BENCHMARK_END (rsa_verify);
1216  return GNUNET_OK;
1217 }
1218 
1219 
1222  const struct GNUNET_CRYPTO_RsaPrivateKey *key)
1223 {
1224  struct GNUNET_CRYPTO_RsaPrivateKey *dup;
1225  gcry_sexp_t dup_sexp;
1226  size_t erroff;
1227 
1228  /* check if we really are exporting a private key */
1229  dup_sexp = gcry_sexp_find_token (key->sexp, "private-key", 0);
1230  GNUNET_assert (NULL != dup_sexp);
1231  gcry_sexp_release (dup_sexp);
1232  /* copy the sexp */
1233  GNUNET_assert (0 == gcry_sexp_build (&dup_sexp, &erroff, "%S", key->sexp));
1234  dup = GNUNET_new (struct GNUNET_CRYPTO_RsaPrivateKey);
1235  dup->sexp = dup_sexp;
1236  return dup;
1237 }
1238 
1239 
1242 {
1243  struct GNUNET_CRYPTO_RsaSignature *dup;
1244  gcry_sexp_t dup_sexp;
1245  size_t erroff;
1246  gcry_mpi_t s;
1247  int ret;
1248 
1249  /* verify that this is an RSA signature */
1250  ret = key_from_sexp (&s, sig->sexp, "sig-val", "s");
1251  if (0 != ret)
1252  ret = key_from_sexp (&s, sig->sexp, "rsa", "s");
1253  GNUNET_assert (0 == ret);
1254  gcry_mpi_release (s);
1255  /* copy the sexp */
1256  GNUNET_assert (0 == gcry_sexp_build (&dup_sexp, &erroff, "%S", sig->sexp));
1257  dup = GNUNET_new (struct GNUNET_CRYPTO_RsaSignature);
1258  dup->sexp = dup_sexp;
1259  return dup;
1260 }
1261 
1262 
1263 /* 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:95
static void rsa_blinding_key_free(struct RsaBlindingKey *bkey)
Destroy a blinding key.
Definition: crypto_rsa.c:702
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:871
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:892
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:754
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:522
#define LOG(kind,...)
Definition: crypto_rsa.c:34
static int rsa_gcd_validate(gcry_mpi_t r, gcry_mpi_t n)
Test for malicious RSA key.
Definition: crypto_rsa.c:501
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:717
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:47
static char buf[2048]
static struct GNUNET_SCHEDULER_Task * t
Main task.
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:1075
#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:1039
void GNUNET_CRYPTO_rsa_signature_free(struct GNUNET_CRYPTO_RsaSignature *sig)
Free memory occupied by signature.
Definition: crypto_rsa.c:991
void GNUNET_CRYPTO_rsa_private_key_free(struct GNUNET_CRYPTO_RsaPrivateKey *key)
Free memory occupied by the private key.
Definition: crypto_rsa.c:173
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:95
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:1175
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:204
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:1094
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:602
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:301
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:680
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:407
void GNUNET_CRYPTO_rsa_public_key_free(struct GNUNET_CRYPTO_RsaPublicKey *key)
Free memory occupied by the public key.
Definition: crypto_rsa.c:268
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:423
#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:325
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:654
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:999
struct GNUNET_CRYPTO_RsaSignature * GNUNET_CRYPTO_rsa_signature_dup(const struct GNUNET_CRYPTO_RsaSignature *sig)
Duplicate the given rsa signature.
Definition: crypto_rsa.c:1241
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:971
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:628
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:233
GNUNET_GenericReturnValue
Named constants for return values.
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:181
struct GNUNET_CRYPTO_RsaPrivateKey * GNUNET_CRYPTO_rsa_private_key_create(unsigned int len)
Create a new private key.
Definition: crypto_rsa.c:144
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:1221
#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:947
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:790
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
@ GNUNET_SYSERR
#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:41
gcry_sexp_t sexp
Libgcrypt S-expression for the RSA private key.
Definition: crypto_rsa.c:45
Format of the header of a serialized RSA public key.
Definition: crypto_rsa.c:281
uint16_t public_exponent_length
length of exponent in bytes, in NBO
Definition: crypto_rsa.c:290
uint16_t modulus_length
length of modulus 'n' in bytes, in NBO
Definition: crypto_rsa.c:285
The public information of an RSA key pair.
Definition: crypto_rsa.c:53
gcry_sexp_t sexp
Libgcrypt S-expression for the RSA public key.
Definition: crypto_rsa.c:57
an RSA signature
Definition: crypto_rsa.c:65
gcry_sexp_t sexp
Libgcrypt S-expression for the RSA signature.
Definition: crypto_rsa.c:69
A 512-bit hashcode.
RSA blinding key.
Definition: crypto_rsa.c:77
gcry_mpi_t r
Random value used for blinding.
Definition: crypto_rsa.c:81