summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/util/Makefile.am2
-rw-r--r--src/util/crypto_rsa.c248
-rw-r--r--src/util/test_crypto_rsa.c33
3 files changed, 215 insertions, 68 deletions
diff --git a/src/util/Makefile.am b/src/util/Makefile.am
index 65b53b91d..c38f19c93 100644
--- a/src/util/Makefile.am
+++ b/src/util/Makefile.am
@@ -483,7 +483,7 @@ test_crypto_random_LDADD = \
483test_crypto_rsa_SOURCES = \ 483test_crypto_rsa_SOURCES = \
484 test_crypto_rsa.c 484 test_crypto_rsa.c
485test_crypto_rsa_LDADD = \ 485test_crypto_rsa_LDADD = \
486 libgnunetutil.la 486 libgnunetutil.la -lgcrypt
487 487
488test_disk_SOURCES = \ 488test_disk_SOURCES = \
489 test_disk.c 489 test_disk.c
diff --git a/src/util/crypto_rsa.c b/src/util/crypto_rsa.c
index 6c58757d8..a14eff407 100644
--- a/src/util/crypto_rsa.c
+++ b/src/util/crypto_rsa.c
@@ -566,16 +566,15 @@ GNUNET_CRYPTO_rsa_blinding_key_free (struct GNUNET_CRYPTO_rsa_BlindingKey *bkey)
566 566
567 567
568/** 568/**
569 * Encode the blinding key in a format suitable for 569 * Print an MPI to a newly created buffer
570 * storing it into a file.
571 * 570 *
572 * @param bkey the blinding key 571 * @param v MPI to print.
573 * @param[out] buffer set to a buffer with the encoded key 572 * @param[out] buffer set to a buffer with the result
574 * @return size of memory allocated in @a buffer 573 * @return number of bytes stored in @a buffer
575 */ 574 */
576size_t 575size_t
577GNUNET_CRYPTO_rsa_blinding_key_encode (const struct GNUNET_CRYPTO_rsa_BlindingKey *bkey, 576GNUNET_CRYPTO_mpi_print (gcry_mpi_t v,
578 char **buffer) 577 char **buffer)
579{ 578{
580 size_t n; 579 size_t n;
581 char *b; 580 char *b;
@@ -585,20 +584,36 @@ GNUNET_CRYPTO_rsa_blinding_key_encode (const struct GNUNET_CRYPTO_rsa_BlindingKe
585 NULL, 584 NULL,
586 0, 585 0,
587 &n, 586 &n,
588 bkey->r); 587 v);
589 b = GNUNET_malloc (n); 588 b = GNUNET_malloc (n);
590 GNUNET_assert (0 == 589 GNUNET_assert (0 ==
591 gcry_mpi_print (GCRYMPI_FMT_USG, 590 gcry_mpi_print (GCRYMPI_FMT_USG,
592 (unsigned char *) b, 591 (unsigned char *) b,
593 n, 592 n,
594 &rsize, 593 &rsize,
595 bkey->r)); 594 v));
596 *buffer = b; 595 *buffer = b;
597 return n; 596 return n;
598} 597}
599 598
600 599
601/** 600/**
601 * Encode the blinding key in a format suitable for
602 * storing it into a file.
603 *
604 * @param bkey the blinding key
605 * @param[out] buffer set to a buffer with the encoded key
606 * @return size of memory allocated in @a buffer
607 */
608size_t
609GNUNET_CRYPTO_rsa_blinding_key_encode (const struct GNUNET_CRYPTO_rsa_BlindingKey *bkey,
610 char **buffer)
611{
612 return GNUNET_CRYPTO_mpi_print (bkey->r, buffer);
613}
614
615
616/**
602 * Decode the blinding key from the data-format back 617 * Decode the blinding key from the data-format back
603 * to the "normal", internal format. 618 * to the "normal", internal format.
604 * 619 *
@@ -630,6 +645,95 @@ GNUNET_CRYPTO_rsa_blinding_key_decode (const char *buf,
630 645
631 646
632/** 647/**
648 * Computes a full domain hash seeded by the given public key.
649 * This gives a measure of provable security to the Taler exchange
650 * against one-more forgery attacks. See:
651 * https://eprint.iacr.org/2001/002.pdf
652 * http://www.di.ens.fr/~pointche/Documents/Papers/2001_fcA.pdf
653 *
654 * @param hash initial hash of the message to sign
655 * @param pkey the public key of the signer
656 * @return libgcrypt error that to represent an allocation failure
657 */
658gcry_error_t
659rsa_full_domain_hash (gcry_mpi_t *r,
660 const struct GNUNET_HashCode *hash,
661 const struct GNUNET_CRYPTO_rsa_PublicKey *pkey,
662 size_t *rsize)
663{
664 int i,nbits,nhashes;
665 gcry_error_t rc;
666 char *buf;
667 size_t buf_len;
668 gcry_md_hd_t h,h0;
669 struct GNUNET_HashCode *hs;
670
671 /* Uncomment the following to debug without using the full domain hash */
672 /*
673 rc = gcry_mpi_scan (r,
674 GCRYMPI_FMT_USG,
675 (const unsigned char *)hash,
676 sizeof(struct GNUNET_HashCode),
677 rsize);
678 return rc;
679 */
680
681 nbits = GNUNET_CRYPTO_rsa_public_key_len (pkey);
682 // calls gcry_mpi_get_nbits(.. pkey->sexp ..)
683 if (nbits < 512)
684 nbits = 512;
685
686 // Already almost an HMAC since we consume a hash, so no GCRY_MD_FLAG_HMAC.
687 rc = gcry_md_open (&h,GCRY_MD_SHA512,0);
688 if (0 != rc) return rc;
689
690 // We seed with the public denomination key as a homage to RSA-PSS by
691 // Mihir Bellare and Phillip Rogaway. Doing this lowers the degree
692 // of the hypothetical polyomial-time attack on RSA-KTI created by a
693 // polynomial-time one-more forgary attack. Yey seeding!
694 buf_len = GNUNET_CRYPTO_rsa_public_key_encode (pkey, &buf);
695 gcry_md_write (h, buf,buf_len);
696 GNUNET_free (buf);
697
698 nhashes = (nbits-1) / (8 * sizeof(struct GNUNET_HashCode)) + 1;
699 hs = (struct GNUNET_HashCode *)GNUNET_malloc (nhashes * sizeof(struct GNUNET_HashCode));
700 for (i=0; i<nhashes; i++)
701 {
702 gcry_md_write (h, hash, sizeof(struct GNUNET_HashCode));
703 rc = gcry_md_copy (&h0, h);
704 if (0 != rc) break;
705 gcry_md_putc (h0, i % 256);
706 // gcry_md_final (&h0);
707 memcpy (&hs[i],
708 gcry_md_read (h0,GCRY_MD_SHA512),
709 sizeof(struct GNUNET_HashCode));
710 gcry_md_close (h0);
711 }
712 gcry_md_close (h);
713 if (0 != rc) {
714 GNUNET_free (hs);
715 return rc;
716 }
717
718 rc = gcry_mpi_scan (r,
719 GCRYMPI_FMT_USG,
720 (const unsigned char *)hs,
721 nhashes * sizeof(struct GNUNET_HashCode),
722 rsize);
723 GNUNET_free (hs);
724 if (0 != rc) return rc;
725
726 // Do not allow *r to exceed n or signatures fail to verify unpredictably.
727 // This happening with gcry_mpi_clear_highbit (*r, nbits-1) so maybe
728 // gcry_mpi_clear_highbit is broken, but setting the highbit sounds good.
729 // (void) fprintf (stderr, "%d %d %d",nbits,nhashes, gcry_mpi_get_nbits(*r));
730 gcry_mpi_set_highbit (*r, nbits-2);
731 // (void) fprintf (stderr, " %d\n",gcry_mpi_get_nbits(*r));
732 return rc;
733}
734
735
736/**
633 * Blinds the given message with the given blinding key 737 * Blinds the given message with the given blinding key
634 * 738 *
635 * @param hash hash of the message to sign 739 * @param hash hash of the message to sign
@@ -651,7 +755,6 @@ GNUNET_CRYPTO_rsa_blind (const struct GNUNET_HashCode *hash,
651 size_t rsize; 755 size_t rsize;
652 size_t n; 756 size_t n;
653 gcry_error_t rc; 757 gcry_error_t rc;
654 char *b;
655 int ret; 758 int ret;
656 759
657 ret = key_from_sexp (ne, pkey->sexp, "public-key", "ne"); 760 ret = key_from_sexp (ne, pkey->sexp, "public-key", "ne");
@@ -663,11 +766,9 @@ GNUNET_CRYPTO_rsa_blind (const struct GNUNET_HashCode *hash,
663 *buffer = NULL; 766 *buffer = NULL;
664 return 0; 767 return 0;
665 } 768 }
666 if (0 != (rc = gcry_mpi_scan (&data, 769
667 GCRYMPI_FMT_USG, 770 rc = rsa_full_domain_hash(&data, hash, pkey, &rsize);
668 (const unsigned char *) hash, 771 if (0 != rc) // Allocation error in libgcrypt
669 sizeof (struct GNUNET_HashCode),
670 &rsize)))
671 { 772 {
672 GNUNET_break (0); 773 GNUNET_break (0);
673 gcry_mpi_release (ne[0]); 774 gcry_mpi_release (ne[0]);
@@ -690,75 +791,50 @@ GNUNET_CRYPTO_rsa_blind (const struct GNUNET_HashCode *hash,
690 gcry_mpi_release (ne[1]); 791 gcry_mpi_release (ne[1]);
691 gcry_mpi_release (r_e); 792 gcry_mpi_release (r_e);
692 793
693 gcry_mpi_print (GCRYMPI_FMT_USG, 794 n = GNUNET_CRYPTO_mpi_print (data_r_e, buffer);
694 NULL,
695 0,
696 &n,
697 data_r_e);
698 b = GNUNET_malloc (n);
699 rc = gcry_mpi_print (GCRYMPI_FMT_USG,
700 (unsigned char *) b,
701 n,
702 &rsize,
703 data_r_e);
704 gcry_mpi_release (data_r_e); 795 gcry_mpi_release (data_r_e);
705 *buffer = b;
706 return n; 796 return n;
707} 797}
708 798
709 799
710/** 800/**
711 * Convert the data specified in the given purpose argument to an 801 * Convert an MPI to an S-expression suitable for signature operations.
712 * S-expression suitable for signature operations.
713 * 802 *
714 * @param ptr pointer to the data to convert 803 * @param value pointer to the data to convert
715 * @param size the size of the data
716 * @return converted s-expression 804 * @return converted s-expression
717 */ 805 */
718static gcry_sexp_t 806static gcry_sexp_t
719data_to_sexp (const void *ptr, size_t size) 807mpi_to_sexp (gcry_mpi_t value)
720{ 808{
721 gcry_mpi_t value; 809 gcry_sexp_t data = NULL;
722 gcry_sexp_t data;
723 810
724 value = NULL;
725 data = NULL;
726 GNUNET_assert (0 ==
727 gcry_mpi_scan (&value,
728 GCRYMPI_FMT_USG,
729 ptr,
730 size,
731 NULL));
732 GNUNET_assert (0 == 811 GNUNET_assert (0 ==
733 gcry_sexp_build (&data, 812 gcry_sexp_build (&data,
734 NULL, 813 NULL,
735 "(data (flags raw) (value %M))", 814 "(data (flags raw) (value %M))",
736 value)); 815 value));
737 gcry_mpi_release (value);
738 return data; 816 return data;
739} 817}
740 818
741 819
742/** 820/**
743 * Sign the given message. 821 * Sign and release the given MPI.
744 * 822 *
745 * @param key private key to use for the signing 823 * @param key private key to use for the signing
746 * @param msg the message to sign 824 * @param value the MPI to sign
747 * @param msg_len number of bytes in @a msg to sign
748 * @return NULL on error, signature on success 825 * @return NULL on error, signature on success
749 */ 826 */
750struct GNUNET_CRYPTO_rsa_Signature * 827struct GNUNET_CRYPTO_rsa_Signature *
751GNUNET_CRYPTO_rsa_sign (const struct GNUNET_CRYPTO_rsa_PrivateKey *key, 828rsa_sign_mpi (const struct GNUNET_CRYPTO_rsa_PrivateKey *key,
752 const void *msg, 829 gcry_mpi_t value)
753 size_t msg_len)
754{ 830{
755 struct GNUNET_CRYPTO_rsa_Signature *sig; 831 struct GNUNET_CRYPTO_rsa_Signature *sig;
756 struct GNUNET_CRYPTO_rsa_PublicKey *public_key; 832 struct GNUNET_CRYPTO_rsa_PublicKey *public_key;
757 gcry_sexp_t result; 833 gcry_sexp_t data,result;
758 gcry_sexp_t data; 834
835 data = mpi_to_sexp (value);
836 gcry_mpi_release (value);
759 837
760 data = data_to_sexp (msg,
761 msg_len);
762 if (0 != 838 if (0 !=
763 gcry_pk_sign (&result, 839 gcry_pk_sign (&result,
764 data, 840 data,
@@ -775,7 +851,7 @@ GNUNET_CRYPTO_rsa_sign (const struct GNUNET_CRYPTO_rsa_PrivateKey *key,
775 data, 851 data,
776 public_key->sexp)) 852 public_key->sexp))
777 { 853 {
778 GNUNET_break (0); 854 GNUNET_break (0);
779 GNUNET_CRYPTO_rsa_public_key_free (public_key); 855 GNUNET_CRYPTO_rsa_public_key_free (public_key);
780 gcry_sexp_release (data); 856 gcry_sexp_release (data);
781 gcry_sexp_release (result); 857 gcry_sexp_release (result);
@@ -792,6 +868,56 @@ GNUNET_CRYPTO_rsa_sign (const struct GNUNET_CRYPTO_rsa_PrivateKey *key,
792 868
793 869
794/** 870/**
871 * Sign a blinded value, which must be a full domain hash of a message.
872 *
873 * @param key private key to use for the signing
874 * @param msg the message to sign
875 * @param msg_len number of bytes in @a msg to sign
876 * @return NULL on error, signature on success
877 */
878struct GNUNET_CRYPTO_rsa_Signature *
879GNUNET_CRYPTO_rsa_sign_blinded (const struct GNUNET_CRYPTO_rsa_PrivateKey *key,
880 const void *msg,
881 size_t msg_len)
882{
883 gcry_mpi_t v = NULL;
884
885 GNUNET_assert (0 ==
886 gcry_mpi_scan (&v,
887 GCRYMPI_FMT_USG,
888 msg,
889 msg_len,
890 NULL));
891
892 return rsa_sign_mpi (key,v);
893}
894
895
896/**
897 * Create and sign a full domain hash of a message.
898 *
899 * @param key private key to use for the signing
900 * @param hash the hash of the message to sign
901 * @return NULL on error, signature on success
902 */
903struct GNUNET_CRYPTO_rsa_Signature *
904GNUNET_CRYPTO_rsa_sign_fdh (const struct GNUNET_CRYPTO_rsa_PrivateKey *key,
905 const struct GNUNET_HashCode *hash)
906{
907 struct GNUNET_CRYPTO_rsa_PublicKey *pkey;
908 gcry_mpi_t v = NULL;
909 gcry_error_t rc;
910
911 pkey = GNUNET_CRYPTO_rsa_private_key_get_public (key);
912 rc = rsa_full_domain_hash (&v, hash, pkey, NULL);
913 GNUNET_CRYPTO_rsa_public_key_free (pkey);
914 GNUNET_assert (0 == rc);
915
916 return rsa_sign_mpi (key,v);
917}
918
919
920/**
795 * Free memory occupied by signature. 921 * Free memory occupied by signature.
796 * 922 *
797 * @param sig memory to freee 923 * @param sig memory to freee
@@ -976,22 +1102,26 @@ GNUNET_CRYPTO_rsa_unblind (struct GNUNET_CRYPTO_rsa_Signature *sig,
976 * 1102 *
977 * @param hash hash of the message to verify to match the @a sig 1103 * @param hash hash of the message to verify to match the @a sig
978 * @param sig signature that is being validated 1104 * @param sig signature that is being validated
979 * @param public_key public key of the signer 1105 * @param pkey public key of the signer
980 * @returns #GNUNET_OK if ok, #GNUNET_SYSERR if invalid 1106 * @returns #GNUNET_OK if ok, #GNUNET_SYSERR if invalid
981 */ 1107 */
982int 1108int
983GNUNET_CRYPTO_rsa_verify (const struct GNUNET_HashCode *hash, 1109GNUNET_CRYPTO_rsa_verify (const struct GNUNET_HashCode *hash,
984 const struct GNUNET_CRYPTO_rsa_Signature *sig, 1110 const struct GNUNET_CRYPTO_rsa_Signature *sig,
985 const struct GNUNET_CRYPTO_rsa_PublicKey *public_key) 1111 const struct GNUNET_CRYPTO_rsa_PublicKey *pkey)
986{ 1112{
987 gcry_sexp_t data; 1113 gcry_sexp_t data;
1114 gcry_mpi_t r;
988 int rc; 1115 int rc;
989 1116
990 data = data_to_sexp (hash, 1117 rc = rsa_full_domain_hash (&r, hash, pkey, NULL);
991 sizeof (struct GNUNET_HashCode)); 1118 GNUNET_assert (0 == rc); // Allocation error in libgcrypt
1119 data = mpi_to_sexp(r);
1120 gcry_mpi_release (r);
1121
992 rc = gcry_pk_verify (sig->sexp, 1122 rc = gcry_pk_verify (sig->sexp,
993 data, 1123 data,
994 public_key->sexp); 1124 pkey->sexp);
995 gcry_sexp_release (data); 1125 gcry_sexp_release (data);
996 if (0 != rc) 1126 if (0 != rc)
997 { 1127 {
diff --git a/src/util/test_crypto_rsa.c b/src/util/test_crypto_rsa.c
index 7580062df..9bd2e6ae5 100644
--- a/src/util/test_crypto_rsa.c
+++ b/src/util/test_crypto_rsa.c
@@ -20,11 +20,19 @@
20 * @author Sree Harsha Totakura <sreeharsha@totakura.in> 20 * @author Sree Harsha Totakura <sreeharsha@totakura.in>
21 */ 21 */
22#include "platform.h" 22#include "platform.h"
23#include <gcrypt.h>
23#include "gnunet_util_lib.h" 24#include "gnunet_util_lib.h"
24 25
25#define KEY_SIZE 1024 26#define KEY_SIZE 1024
26 27
27 28
29gcry_error_t
30rsa_full_domain_hash (gcry_mpi_t *r,
31 const struct GNUNET_HashCode *hash,
32 const struct GNUNET_CRYPTO_rsa_PublicKey *pkey,
33 size_t *rsize);
34
35
28int 36int
29main (int argc, 37main (int argc,
30 char *argv[]) 38 char *argv[])
@@ -42,6 +50,7 @@ main (int argc,
42 struct GNUNET_HashCode hash; 50 struct GNUNET_HashCode hash;
43 char *blind_buf; 51 char *blind_buf;
44 size_t bsize; 52 size_t bsize;
53 gcry_mpi_t v;
45 54
46 GNUNET_log_setup ("test-rsa", "WARNING", NULL); 55 GNUNET_log_setup ("test-rsa", "WARNING", NULL);
47 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, 56 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
@@ -55,11 +64,13 @@ main (int argc,
55 GNUNET_assert (NULL != priv_copy); 64 GNUNET_assert (NULL != priv_copy);
56 GNUNET_assert (0 == GNUNET_CRYPTO_rsa_private_key_cmp (priv, priv_copy)); 65 GNUNET_assert (0 == GNUNET_CRYPTO_rsa_private_key_cmp (priv, priv_copy));
57 pub = GNUNET_CRYPTO_rsa_private_key_get_public (priv); 66 pub = GNUNET_CRYPTO_rsa_private_key_get_public (priv);
67
58 /* Encoding */ 68 /* Encoding */
59 size_t size; 69 size_t size;
60 char *enc; 70 char *enc;
61 enc = NULL; 71 enc = NULL;
62 size = GNUNET_CRYPTO_rsa_private_key_encode (priv, &enc); 72 size = GNUNET_CRYPTO_rsa_private_key_encode (priv, &enc);
73
63 /* Decoding */ 74 /* Decoding */
64 GNUNET_CRYPTO_rsa_private_key_free (priv); 75 GNUNET_CRYPTO_rsa_private_key_free (priv);
65 priv = NULL; 76 priv = NULL;
@@ -71,10 +82,17 @@ main (int argc,
71 (void) fprintf (stderr, "The above warning is expected.\n"); 82 (void) fprintf (stderr, "The above warning is expected.\n");
72 GNUNET_free (enc); 83 GNUNET_free (enc);
73 84
85 /* test full domain hash size */
86 GNUNET_assert (0 == rsa_full_domain_hash (&v, &hash, pub, NULL));
87 GNUNET_assert (gcry_mpi_get_nbits(v) < KEY_SIZE);
88 gcry_mpi_clear_highbit (v, gcry_mpi_get_nbits(v)-1); /* clear the set high bit */
89 GNUNET_assert (gcry_mpi_get_nbits(v) > 3*KEY_SIZE/4);
90 /* This test necessarily randomly fails with probability 2^(3 - KEY_SIZE/4) */
91 gcry_mpi_release(v);
92
74 /* try ordinary sig first */ 93 /* try ordinary sig first */
75 sig = GNUNET_CRYPTO_rsa_sign (priv, 94 sig = GNUNET_CRYPTO_rsa_sign_fdh (priv,
76 &hash, 95 &hash);
77 sizeof (hash));
78 sig_copy = GNUNET_CRYPTO_rsa_signature_dup (sig); 96 sig_copy = GNUNET_CRYPTO_rsa_signature_dup (sig);
79 GNUNET_assert (NULL != sig); 97 GNUNET_assert (NULL != sig);
80 GNUNET_assert (0 == GNUNET_CRYPTO_rsa_signature_cmp (sig, sig_copy)); 98 GNUNET_assert (0 == GNUNET_CRYPTO_rsa_signature_cmp (sig, sig_copy));
@@ -91,7 +109,6 @@ main (int argc,
91 (void) fprintf (stderr, "The above warning is expected.\n"); 109 (void) fprintf (stderr, "The above warning is expected.\n");
92 GNUNET_CRYPTO_rsa_signature_free (sig); 110 GNUNET_CRYPTO_rsa_signature_free (sig);
93 111
94
95 /* test blind signing */ 112 /* test blind signing */
96 bkey = GNUNET_CRYPTO_rsa_blinding_key_create (KEY_SIZE); 113 bkey = GNUNET_CRYPTO_rsa_blinding_key_create (KEY_SIZE);
97 bsize = GNUNET_CRYPTO_rsa_blind (&hash, 114 bsize = GNUNET_CRYPTO_rsa_blind (&hash,
@@ -99,16 +116,16 @@ main (int argc,
99 pub, 116 pub,
100 &blind_buf); 117 &blind_buf);
101 GNUNET_assert (0 != bsize); 118 GNUNET_assert (0 != bsize);
102 bsig = GNUNET_CRYPTO_rsa_sign (priv, 119 bsig = GNUNET_CRYPTO_rsa_sign_blinded (priv,
103 blind_buf, 120 blind_buf,
104 bsize); 121 bsize);
105 GNUNET_free (blind_buf); 122 GNUNET_free (blind_buf);
106 sig = GNUNET_CRYPTO_rsa_unblind (bsig, 123 sig = GNUNET_CRYPTO_rsa_unblind (bsig,
107 bkey, 124 bkey,
108 pub); 125 pub);
109 GNUNET_CRYPTO_rsa_signature_free (bsig); 126 GNUNET_CRYPTO_rsa_signature_free (bsig);
110 GNUNET_assert (GNUNET_OK == 127 GNUNET_assert (GNUNET_OK ==
111 GNUNET_CRYPTO_rsa_verify (&hash, sig, pub)); 128 GNUNET_CRYPTO_rsa_verify (&hash, sig, pub));
112 GNUNET_CRYPTO_rsa_signature_free (sig); 129 GNUNET_CRYPTO_rsa_signature_free (sig);
113 GNUNET_CRYPTO_rsa_signature_free (sig_copy); 130 GNUNET_CRYPTO_rsa_signature_free (sig_copy);
114 GNUNET_CRYPTO_rsa_private_key_free (priv); 131 GNUNET_CRYPTO_rsa_private_key_free (priv);