GNUnet 0.21.1
crypto_rsa.c
Go to the documentation of this file.
1/*
2 This file is part of GNUnet
3 Copyright (C) 2014,2016,2019,2023 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
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
94static int
95key_from_sexp (gcry_mpi_t *array,
96 gcry_sexp_t sexp,
97 const char *topname,
98 const char *elems)
99{
100 gcry_sexp_t list;
101 gcry_sexp_t l2;
102 const char *s;
103 unsigned int idx;
104
105 if (! (list = gcry_sexp_find_token (sexp, topname, 0)))
106 return 1;
107 l2 = gcry_sexp_cadr (list);
108 gcry_sexp_release (list);
109 list = l2;
110 if (! list)
111 return 2;
112 idx = 0;
113 for (s = elems; *s; s++, idx++)
114 {
115 if (! (l2 = gcry_sexp_find_token (list, s, 1)))
116 {
117 for (unsigned int i = 0; i < idx; i++)
118 {
119 gcry_free (array[i]);
120 array[i] = NULL;
121 }
122 gcry_sexp_release (list);
123 return 3; /* required parameter not found */
124 }
125 array[idx] = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
126 gcry_sexp_release (l2);
127 if (! array[idx])
128 {
129 for (unsigned int i = 0; i < idx; i++)
130 {
131 gcry_free (array[i]);
132 array[i] = NULL;
133 }
134 gcry_sexp_release (list);
135 return 4; /* required parameter is invalid */
136 }
137 }
138 gcry_sexp_release (list);
139 return 0;
140}
141
142
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
172void
174{
175 gcry_sexp_release (key->sexp);
177}
178
179
180size_t
182 const struct GNUNET_CRYPTO_RsaPrivateKey *key,
183 void **buffer)
184{
185 size_t n;
186 char *b;
187
188 n = gcry_sexp_sprint (key->sexp,
189 GCRYSEXP_FMT_DEFAULT,
190 NULL,
191 0);
192 b = GNUNET_malloc (n);
193 GNUNET_assert ((n - 1) == /* since the last byte is \0 */
194 gcry_sexp_sprint (key->sexp,
195 GCRYSEXP_FMT_DEFAULT,
196 b,
197 n));
198 *buffer = b;
199 return n;
200}
201
202
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");
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
267void
269{
270 gcry_sexp_release (key->sexp);
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
300bool
302 const struct GNUNET_CRYPTO_RsaPublicKey *key)
303{
304 gcry_mpi_t ne[2];
305 int ret;
306
307 ret = key_from_sexp (ne,
308 key->sexp,
309 "public-key",
310 "ne");
311 if (0 != ret)
312 ret = key_from_sexp (ne,
313 key->sexp,
314 "rsa",
315 "ne");
316 if (0 != ret)
317 return false;
318 gcry_mpi_release (ne[0]);
319 gcry_mpi_release (ne[1]);
320 return true;
321}
322
323
324size_t
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
406void
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
500static int
501rsa_gcd_validate (gcry_mpi_t r,
502 gcry_mpi_t n)
503{
504 gcry_mpi_t g;
505 int t;
506
507 g = gcry_mpi_new (0);
508 t = gcry_mpi_gcd (g, r, n);
509 gcry_mpi_release (g);
510 return t;
511}
512
513
521static 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));
542 n,
543 xts, strlen (xts),
544 bks, sizeof(*bks),
545 "Blinding KDF");
546 if (0 == rsa_gcd_validate (blind->r,
547 n))
548 {
549 gcry_mpi_release (blind->r);
550 GNUNET_free (blind);
551 blind = NULL;
552 }
553 gcry_mpi_release (n);
554 return blind;
555}
556
557
558/*
559 We originally added GNUNET_CRYPTO_kdf_mod_mpi for the benefit of the
560 previous routine.
561
562 There was previously a call to GNUNET_CRYPTO_kdf in
563 bkey = rsa_blinding_key_derive (len, bks);
564 that gives exactly len bits where
565 len = GNUNET_CRYPTO_rsa_public_key_len (pkey);
566
567 Now r = 2^(len-1)/pkey.n is the probability that a set high bit being
568 okay, meaning bkey < pkey.n. It follows that (1-r)/2 of the time bkey >
569 pkey.n making the effective bkey be
570 bkey mod pkey.n = bkey - pkey.n
571 so the effective bkey has its high bit set with probability r/2.
572
573 We expect r to be close to 1/2 if the exchange is honest, but the
574 exchange can choose r otherwise.
575
576 In blind signing, the exchange sees
577 B = bkey * S mod pkey.n
578 On deposit, the exchange sees S so they can compute bkey' = B/S mod
579 pkey.n for all B they recorded to see if bkey' has it's high bit set.
580 Also, note the exchange can compute 1/S efficiently since they know the
581 factors of pkey.n.
582
583 I suppose that happens with probability r/(1+r) if its the wrong B, not
584 completely sure. If otoh we've the right B, then we've the probability
585 r/2 of a set high bit in the effective bkey.
586
587 Interestingly, r^2-r has a maximum at the default r=1/2 anyways, giving
588 the wrong and right probabilities 1/3 and 1/4, respectively.
589
590 I feared this gives the exchange a meaningful fraction of a bit of
591 information per coin involved in the transaction. It sounds damaging if
592 numerous coins were involved. And it could run across transactions in
593 some scenarios.
594
595 We fixed this by using a more uniform deterministic pseudo-random number
596 generator for blinding factors. I do not believe this to be a problem
597 for the rsa_full_domain_hash routine, but better safe than sorry.
598 */
599
600
601int
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
627int
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
653int
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
679unsigned 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
701static void
703{
704 gcry_mpi_release (bkey->r);
705 GNUNET_free (bkey);
706}
707
708
716static 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
754static gcry_mpi_t
756 const void *message,
757 size_t message_size)
758{
759 gcry_mpi_t r;
760 gcry_mpi_t n;
761 void *xts;
762 size_t xts_len;
763 int ok;
764
765 /* Extract the composite n from the RSA public key */
766 GNUNET_assert (0 ==
767 key_from_sexp (&n,
768 pkey->sexp,
769 "rsa",
770 "n"));
771 /* Assert that it at least looks like an RSA key */
772 GNUNET_assert (0 ==
773 gcry_mpi_get_flag (n,
774 GCRYMPI_FLAG_OPAQUE));
775
776 /* We key with the public denomination key as a homage to RSA-PSS by *
777 * Mihir Bellare and Phillip Rogaway. Doing this lowers the degree *
778 * of the hypothetical polyomial-time attack on RSA-KTI created by a *
779 * polynomial-time one-more forgary attack. Yey seeding! */
781 &xts);
782
784 n,
785 xts, xts_len,
786 message, message_size,
787 "RSA-FDA FTpsW!");
788 GNUNET_free (xts);
789 ok = rsa_gcd_validate (r, n);
790 gcry_mpi_release (n);
791 if (ok)
792 return r;
793 gcry_mpi_release (r);
794 return NULL;
795}
796
797
798void
801{
803}
804
805
807GNUNET_CRYPTO_rsa_blind (const void *message,
808 size_t message_size,
809 const struct GNUNET_CRYPTO_RsaBlindingKeySecret *bks,
812{
813 struct RsaBlindingKey *bkey;
814 gcry_mpi_t data;
815 gcry_mpi_t ne[2];
816 gcry_mpi_t r_e;
817 gcry_mpi_t data_r_e;
818 int ret;
819
820 BENCHMARK_START (rsa_blind);
821 ret = key_from_sexp (ne,
822 pkey->sexp,
823 "public-key",
824 "ne");
825 if (0 != ret)
826 ret = key_from_sexp (ne,
827 pkey->sexp,
828 "rsa",
829 "ne");
830 if (0 != ret)
831 {
832 GNUNET_break (0);
833 bm->blinded_msg = NULL;
834 bm->blinded_msg_size = 0;
835 BENCHMARK_END (rsa_blind);
836 return GNUNET_NO;
837 }
838
840 message,
841 message_size);
842 if (NULL == data)
843 goto rsa_gcd_validate_failure;
845 bks);
846 if (NULL == bkey)
847 {
848 gcry_mpi_release (data);
849 goto rsa_gcd_validate_failure;
850 }
851 r_e = gcry_mpi_new (0);
852 gcry_mpi_powm (r_e,
853 bkey->r,
854 ne[1],
855 ne[0]);
856 data_r_e = gcry_mpi_new (0);
857 gcry_mpi_mulm (data_r_e,
858 data,
859 r_e,
860 ne[0]);
861 gcry_mpi_release (data);
862 gcry_mpi_release (ne[0]);
863 gcry_mpi_release (ne[1]);
864 gcry_mpi_release (r_e);
866
868 = numeric_mpi_alloc_n_print (data_r_e,
869 (char **) &bm->blinded_msg);
870 gcry_mpi_release (data_r_e);
871
872 BENCHMARK_END (rsa_blind);
873 return GNUNET_YES;
874
875rsa_gcd_validate_failure:
876 /* We know the RSA key is malicious here, so warn the wallet. */
877 /* GNUNET_break_op (0); */
878 gcry_mpi_release (ne[0]);
879 gcry_mpi_release (ne[1]);
880 bm->blinded_msg = NULL;
881 bm->blinded_msg_size = 0;
882 BENCHMARK_END (rsa_blind);
883 return GNUNET_NO;
884}
885
886
893static gcry_sexp_t
894mpi_to_sexp (gcry_mpi_t value)
895{
896 gcry_sexp_t data = NULL;
897
898 GNUNET_assert (0 ==
899 gcry_sexp_build (&data,
900 NULL,
901 "(data (flags raw) (value %M))",
902 value));
903 return data;
904}
905
906
914static struct GNUNET_CRYPTO_RsaSignature *
916 gcry_mpi_t value)
917{
918 struct GNUNET_CRYPTO_RsaSignature *sig;
919 gcry_sexp_t data;
920 gcry_sexp_t result;
921 int rc;
922
924
925 if (0 !=
926 (rc = gcry_pk_sign (&result,
927 data,
928 key->sexp)))
929 {
931 _ ("RSA signing failed at %s:%d: %s\n"),
932 __FILE__,
933 __LINE__,
934 gcry_strerror (rc));
935 gcry_sexp_release (data);
936 GNUNET_break (0);
937 return NULL;
938 }
939
940 /* Lenstra protection was first added to libgcrypt 1.6.4
941 * with commit c17f84bd02d7ee93845e92e20f6ddba814961588.
942 */
943#if GCRYPT_VERSION_NUMBER < 0x010604
944 /* verify signature (guards against Lenstra's attack with fault injection...) */
945 struct GNUNET_CRYPTO_RsaPublicKey *public_key =
947 if (0 !=
948 gcry_pk_verify (result,
949 data,
950 public_key->sexp))
951 {
952 GNUNET_break (0);
954 gcry_sexp_release (data);
955 gcry_sexp_release (result);
956 return NULL;
957 }
959#endif
960
961 /* return signature */
962 gcry_sexp_release (data);
964 sig->sexp = result;
965 return sig;
966}
967
968
971 const struct GNUNET_CRYPTO_RsaBlindedMessage *bm)
972{
973 gcry_mpi_t v = NULL;
974 struct GNUNET_CRYPTO_RsaSignature *sig;
975
976 BENCHMARK_START (rsa_sign_blinded);
977 GNUNET_assert (0 ==
978 gcry_mpi_scan (&v,
979 GCRYMPI_FMT_USG,
980 bm->blinded_msg,
982 NULL));
983 sig = rsa_sign_mpi (key,
984 v);
985 gcry_mpi_release (v);
986 BENCHMARK_END (rsa_sign_blinded);
987 return sig;
988}
989
990
993 const void *message,
994 size_t message_size)
995{
997 gcry_mpi_t v = NULL;
998 struct GNUNET_CRYPTO_RsaSignature *sig;
999
1002 message,
1003 message_size);
1005 if (NULL == v) /* rsa_gcd_validate failed meaning */
1006 return NULL; /* our *own* RSA key is malicious. */
1007
1008 sig = rsa_sign_mpi (key, v);
1009 gcry_mpi_release (v);
1010 return sig;
1011}
1012
1013
1014void
1016{
1017 gcry_sexp_release (sig->sexp);
1018 GNUNET_free (sig);
1019}
1020
1021
1022size_t
1024 const struct GNUNET_CRYPTO_RsaSignature *sig,
1025 void **buffer)
1026{
1027 gcry_mpi_t s;
1028 size_t buf_size;
1029 size_t rsize;
1030 unsigned char *buf;
1031 int ret;
1032
1033 ret = key_from_sexp (&s,
1034 sig->sexp,
1035 "sig-val",
1036 "s");
1037 if (0 != ret)
1038 ret = key_from_sexp (&s,
1039 sig->sexp,
1040 "rsa",
1041 "s");
1042 GNUNET_assert (0 == ret);
1043 gcry_mpi_print (GCRYMPI_FMT_USG,
1044 NULL,
1045 0,
1046 &buf_size,
1047 s);
1048 buf = GNUNET_malloc (buf_size);
1049 GNUNET_assert (0 ==
1050 gcry_mpi_print (GCRYMPI_FMT_USG,
1051 buf,
1052 buf_size,
1053 &rsize,
1054 s));
1055 GNUNET_assert (rsize == buf_size);
1056 *buffer = (void *) buf;
1057 gcry_mpi_release (s);
1058 return buf_size;
1059}
1060
1061
1064 size_t buf_size)
1065{
1066 struct GNUNET_CRYPTO_RsaSignature *sig;
1067 gcry_mpi_t s;
1068 gcry_sexp_t data;
1069
1070 if (0 !=
1071 gcry_mpi_scan (&s,
1072 GCRYMPI_FMT_USG,
1073 buf,
1074 buf_size,
1075 NULL))
1076 {
1077 GNUNET_break_op (0);
1078 return NULL;
1079 }
1080
1081 if (0 !=
1082 gcry_sexp_build (&data,
1083 NULL,
1084 "(sig-val(rsa(s %M)))",
1085 s))
1086 {
1087 GNUNET_break (0);
1088 gcry_mpi_release (s);
1089 return NULL;
1090 }
1091 gcry_mpi_release (s);
1093 sig->sexp = data;
1094 return sig;
1095}
1096
1097
1100{
1101 struct GNUNET_CRYPTO_RsaPublicKey *dup;
1102 gcry_sexp_t dup_sexp;
1103 size_t erroff;
1104
1105 /* check if we really are exporting a public key */
1106 dup_sexp = gcry_sexp_find_token (key->sexp, "public-key", 0);
1107 GNUNET_assert (NULL != dup_sexp);
1108 gcry_sexp_release (dup_sexp);
1109 /* copy the sexp */
1110 GNUNET_assert (0 == gcry_sexp_build (&dup_sexp, &erroff, "%S", key->sexp));
1112 dup->sexp = dup_sexp;
1113 return dup;
1114}
1115
1116
1119 const struct GNUNET_CRYPTO_RsaBlindingKeySecret *bks,
1121{
1122 struct RsaBlindingKey *bkey;
1123 gcry_mpi_t n;
1124 gcry_mpi_t s;
1125 gcry_mpi_t r_inv;
1126 gcry_mpi_t ubsig;
1127 int ret;
1128 struct GNUNET_CRYPTO_RsaSignature *sret;
1129
1130 BENCHMARK_START (rsa_unblind);
1131
1132 ret = key_from_sexp (&n, pkey->sexp, "public-key", "n");
1133 if (0 != ret)
1134 ret = key_from_sexp (&n, pkey->sexp, "rsa", "n");
1135 if (0 != ret)
1136 {
1137 GNUNET_break_op (0);
1138 return NULL;
1139 }
1140 ret = key_from_sexp (&s, sig->sexp, "sig-val", "s");
1141 if (0 != ret)
1142 ret = key_from_sexp (&s, sig->sexp, "rsa", "s");
1143 if (0 != ret)
1144 {
1145 gcry_mpi_release (n);
1146 GNUNET_break_op (0);
1147 return NULL;
1148 }
1149
1150 bkey = rsa_blinding_key_derive (pkey, bks);
1151 if (NULL == bkey)
1152 {
1153 /* RSA key is malicious since rsa_gcd_validate failed here.
1154 * It should have failed during GNUNET_CRYPTO_rsa_blind too though,
1155 * so the exchange is being malicious in an unfamilair way, maybe
1156 * just trying to crash us. */
1157 GNUNET_break_op (0);
1158 gcry_mpi_release (n);
1159 gcry_mpi_release (s);
1160 return NULL;
1161 }
1162
1163 r_inv = gcry_mpi_new (0);
1164 if (1 !=
1165 gcry_mpi_invm (r_inv,
1166 bkey->r,
1167 n))
1168 {
1169 /* We cannot find r mod n, so gcd(r,n) != 1, which should get *
1170 * caught above, but we handle it the same here. */
1171 GNUNET_break_op (0);
1172 gcry_mpi_release (r_inv);
1173 rsa_blinding_key_free (bkey);
1174 gcry_mpi_release (n);
1175 gcry_mpi_release (s);
1176 return NULL;
1177 }
1178
1179 ubsig = gcry_mpi_new (0);
1180 gcry_mpi_mulm (ubsig, s, r_inv, n);
1181 gcry_mpi_release (n);
1182 gcry_mpi_release (r_inv);
1183 gcry_mpi_release (s);
1184 rsa_blinding_key_free (bkey);
1185
1186 sret = GNUNET_new (struct GNUNET_CRYPTO_RsaSignature);
1187 GNUNET_assert (0 ==
1188 gcry_sexp_build (&sret->sexp,
1189 NULL,
1190 "(sig-val (rsa (s %M)))",
1191 ubsig));
1192 gcry_mpi_release (ubsig);
1193 BENCHMARK_END (rsa_unblind);
1194 return sret;
1195}
1196
1197
1199GNUNET_CRYPTO_rsa_verify (const void *message,
1200 size_t message_size,
1201 const struct GNUNET_CRYPTO_RsaSignature *sig,
1202 const struct GNUNET_CRYPTO_RsaPublicKey *pkey)
1203{
1204 gcry_sexp_t data;
1205 gcry_mpi_t r;
1206 int rc;
1207
1208 BENCHMARK_START (rsa_verify);
1209
1211 message,
1212 message_size);
1213 if (NULL == r)
1214 {
1215 GNUNET_break_op (0);
1216 /* RSA key is malicious since rsa_gcd_validate failed here.
1217 * It should have failed during GNUNET_CRYPTO_rsa_blind too though,
1218 * so the exchange is being malicious in an unfamilair way, maybe
1219 * just trying to crash us. Arguably, we've only an internal error
1220 * though because we should've detected this in our previous call
1221 * to GNUNET_CRYPTO_rsa_unblind. *///
1222 return GNUNET_NO;
1223 }
1224
1225 data = mpi_to_sexp (r);
1226 gcry_mpi_release (r);
1227
1228 rc = gcry_pk_verify (sig->sexp,
1229 data,
1230 pkey->sexp);
1231 gcry_sexp_release (data);
1232 if (0 != rc)
1233 {
1235 _ ("RSA signature verification failed at %s:%d: %s\n"),
1236 __FILE__,
1237 __LINE__,
1238 gcry_strerror (rc));
1239 BENCHMARK_END (rsa_verify);
1240 return GNUNET_SYSERR;
1241 }
1242 BENCHMARK_END (rsa_verify);
1243 return GNUNET_OK;
1244}
1245
1246
1249 const struct GNUNET_CRYPTO_RsaPrivateKey *key)
1250{
1251 struct GNUNET_CRYPTO_RsaPrivateKey *dup;
1252 gcry_sexp_t dup_sexp;
1253 size_t erroff;
1254
1255 /* check if we really are exporting a private key */
1256 dup_sexp = gcry_sexp_find_token (key->sexp, "private-key", 0);
1257 GNUNET_assert (NULL != dup_sexp);
1258 gcry_sexp_release (dup_sexp);
1259 /* copy the sexp */
1260 GNUNET_assert (0 == gcry_sexp_build (&dup_sexp, &erroff, "%S", key->sexp));
1262 dup->sexp = dup_sexp;
1263 return dup;
1264}
1265
1266
1269{
1270 struct GNUNET_CRYPTO_RsaSignature *dup;
1271 gcry_sexp_t dup_sexp;
1272 size_t erroff;
1273 gcry_mpi_t s;
1274 int ret;
1275
1276 /* verify that this is an RSA signature */
1277 ret = key_from_sexp (&s, sig->sexp, "sig-val", "s");
1278 if (0 != ret)
1279 ret = key_from_sexp (&s, sig->sexp, "rsa", "s");
1280 GNUNET_assert (0 == ret);
1281 gcry_mpi_release (s);
1282 /* copy the sexp */
1283 GNUNET_assert (0 == gcry_sexp_build (&dup_sexp, &erroff, "%S", sig->sexp));
1285 dup->sexp = dup_sexp;
1286 return dup;
1287}
1288
1289
1290/* end of crypto_rsa.c */
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 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
static void rsa_blinding_key_free(struct RsaBlindingKey *bkey)
Destroy a blinding key.
Definition: crypto_rsa.c:702
static gcry_mpi_t rsa_full_domain_hash(const struct GNUNET_CRYPTO_RsaPublicKey *pkey, const void *message, size_t message_size)
Computes a full domain hash seeded by the given public key.
Definition: crypto_rsa.c:755
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:915
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:894
#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 list
Set if we should print a list of currently running services.
Definition: gnunet-arm.c:69
static int ret
Final status code.
Definition: gnunet-arm.c:94
static char * data
The data to insert into the dht.
struct GNUNET_HashCode key
The key used in the DHT.
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 result
Global testing status.
static struct GNUNET_CRYPTO_EddsaPublicKey pub
Definition: gnunet-scrypt.c:47
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
#define GNUNET_NETWORK_STRUCT_BEGIN
Define as empty, GNUNET_PACKED should suffice, but this won't work on W32.
void GNUNET_CRYPTO_rsa_signature_free(struct GNUNET_CRYPTO_RsaSignature *sig)
Free memory occupied by signature.
Definition: crypto_rsa.c:1015
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_rsa_blind(const void *message, size_t message_size, const struct GNUNET_CRYPTO_RsaBlindingKeySecret *bks, struct GNUNET_CRYPTO_RsaPublicKey *pkey, struct GNUNET_CRYPTO_RsaBlindedMessage *bm)
Blinds the given message with the given blinding key.
Definition: crypto_rsa.c:807
struct GNUNET_CRYPTO_RsaPrivateKey * GNUNET_CRYPTO_rsa_private_key_create(unsigned int len)
Create a new private key.
Definition: crypto_rsa.c:144
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
struct GNUNET_CRYPTO_RsaSignature * GNUNET_CRYPTO_rsa_signature_dup(const struct GNUNET_CRYPTO_RsaSignature *sig)
Duplicate the given rsa signature.
Definition: crypto_rsa.c:1268
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:1063
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
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_blinded_message_free(struct GNUNET_CRYPTO_RsaBlindedMessage *bm)
Free memory occupied by blinded message.
Definition: crypto_rsa.c:799
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:1099
struct GNUNET_CRYPTO_RsaSignature * GNUNET_CRYPTO_rsa_sign_fdh(const struct GNUNET_CRYPTO_RsaPrivateKey *key, const void *message, size_t message_size)
Create and sign a full domain hash of a message.
Definition: crypto_rsa.c:992
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
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
void GNUNET_CRYPTO_rsa_public_key_free(struct GNUNET_CRYPTO_RsaPublicKey *key)
Free memory occupied by the public key.
Definition: crypto_rsa.c:268
#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:1023
struct GNUNET_CRYPTO_RsaSignature * GNUNET_CRYPTO_rsa_sign_blinded(const struct GNUNET_CRYPTO_RsaPrivateKey *key, const struct GNUNET_CRYPTO_RsaBlindedMessage *bm)
Sign a blinded value, which must be 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:628
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:1248
GNUNET_GenericReturnValue
Named constants for return values.
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:1118
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
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_rsa_verify(const void *message, size_t message_size, 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:1199
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
#define GNUNET_PACKED
gcc-ism to get packed structs.
@ 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:178
RSA Parameters to create blinded signature.
size_t blinded_msg_size
Size of the blinded_msg to be signed.
void * blinded_msg
Blinded message to be signed Note: is malloc()'ed!
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