aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/include/gnunet_crypto_lib.h21
-rw-r--r--src/util/crypto_kdf.c68
-rw-r--r--src/util/crypto_rsa.c173
-rw-r--r--src/util/test_crypto_rsa.c17
4 files changed, 130 insertions, 149 deletions
diff --git a/src/include/gnunet_crypto_lib.h b/src/include/gnunet_crypto_lib.h
index bd95ad3c3..32503eaf8 100644
--- a/src/include/gnunet_crypto_lib.h
+++ b/src/include/gnunet_crypto_lib.h
@@ -27,6 +27,7 @@
27 * @author Gerd Knorr <kraxel@bytesex.org> 27 * @author Gerd Knorr <kraxel@bytesex.org>
28 * @author Ioana Patrascu 28 * @author Ioana Patrascu
29 * @author Tzvetan Horozov 29 * @author Tzvetan Horozov
30 * @author Jeffrey Burdges <burdges@gnunet.org>
30 * 31 *
31 * @defgroup crypto Crypto library: cryptographic operations 32 * @defgroup crypto Crypto library: cryptographic operations
32 * Provides cryptographic primitives. 33 * Provides cryptographic primitives.
@@ -1015,6 +1016,26 @@ GNUNET_CRYPTO_kdf_v (void *result,
1015 1016
1016 1017
1017/** 1018/**
1019 * Deterministically generate a pseudo-random number uniformly from the
1020 * integers modulo a libgcrypt mpi.
1021 *
1022 * @param[out] r MPI value set to the FDH
1023 * @param n MPI to work modulo
1024 * @param xts salt
1025 * @param xts_len length of @a xts
1026 * @param skm source key material
1027 * @param skm_len length of @a skm
1028 * @param ctx context string
1029 */
1030void
1031GNUNET_CRYPTO_kdf_mod_mpi (gcry_mpi_t *r,
1032 gcry_mpi_t n,
1033 const void *xts, size_t xts_len,
1034 const void *skm, size_t skm_len,
1035 const char *ctx);
1036
1037
1038/**
1018 * @ingroup hash 1039 * @ingroup hash
1019 * @brief Derive key 1040 * @brief Derive key
1020 * @param result buffer for the derived key, allocated by caller 1041 * @param result buffer for the derived key, allocated by caller
diff --git a/src/util/crypto_kdf.c b/src/util/crypto_kdf.c
index 242fbf296..056fda529 100644
--- a/src/util/crypto_kdf.c
+++ b/src/util/crypto_kdf.c
@@ -22,6 +22,7 @@
22 * @file src/util/crypto_kdf.c 22 * @file src/util/crypto_kdf.c
23 * @brief Key derivation 23 * @brief Key derivation
24 * @author Nils Durner 24 * @author Nils Durner
25 * @author Jeffrey Burdges <burdges@gnunet.org>
25 */ 26 */
26 27
27#include <gcrypt.h> 28#include <gcrypt.h>
@@ -43,8 +44,9 @@
43 * @return #GNUNET_YES on success 44 * @return #GNUNET_YES on success
44 */ 45 */
45int 46int
46GNUNET_CRYPTO_kdf_v (void *result, size_t out_len, const void *xts, 47GNUNET_CRYPTO_kdf_v (void *result, size_t out_len,
47 size_t xts_len, const void *skm, size_t skm_len, 48 const void *xts, size_t xts_len,
49 const void *skm, size_t skm_len,
48 va_list argp) 50 va_list argp)
49{ 51{
50 /* 52 /*
@@ -76,8 +78,9 @@ GNUNET_CRYPTO_kdf_v (void *result, size_t out_len, const void *xts,
76 * @return #GNUNET_YES on success 78 * @return #GNUNET_YES on success
77 */ 79 */
78int 80int
79GNUNET_CRYPTO_kdf (void *result, size_t out_len, const void *xts, 81GNUNET_CRYPTO_kdf (void *result, size_t out_len,
80 size_t xts_len, const void *skm, size_t skm_len, ...) 82 const void *xts, size_t xts_len,
83 const void *skm, size_t skm_len, ...)
81{ 84{
82 va_list argp; 85 va_list argp;
83 int ret; 86 int ret;
@@ -88,3 +91,60 @@ GNUNET_CRYPTO_kdf (void *result, size_t out_len, const void *xts,
88 91
89 return ret; 92 return ret;
90} 93}
94
95
96/**
97 * Deterministically generate a pseudo-random number uniformly from the
98 * integers modulo a libgcrypt mpi.
99 *
100 * @param[out] r MPI value set to the FDH
101 * @param n MPI to work modulo
102 * @param xts salt
103 * @param xts_len length of @a xts
104 * @param skm source key material
105 * @param skm_len length of @a skm
106 * @param ctx context string
107 */
108void
109GNUNET_CRYPTO_kdf_mod_mpi (gcry_mpi_t *r,
110 gcry_mpi_t n,
111 const void *xts, size_t xts_len,
112 const void *skm, size_t skm_len,
113 const char *ctx)
114{
115 gcry_error_t rc;
116 unsigned int nbits;
117 size_t rsize;
118 unsigned int ctr;
119
120 nbits = gcry_mpi_get_nbits (n);
121 /* GNUNET_assert (nbits > 512); */
122
123 ctr = 0;
124 do {
125 /* Ain't clear if n is always divisible by 8 */
126 uint8_t buf[ (nbits-1)/8 + 1 ];
127
128 rc = GNUNET_CRYPTO_kdf (buf,
129 sizeof (buf),
130 xts, xts_len,
131 skm, skm_len,
132 ctx, strlen(ctx),
133 &ctr, sizeof(ctr),
134 NULL, 0);
135 GNUNET_assert (GNUNET_YES == rc);
136
137 rc = gcry_mpi_scan (r,
138 GCRYMPI_FMT_USG,
139 (const unsigned char *) buf,
140 sizeof (buf),
141 &rsize);
142 GNUNET_assert (0 == rc); /* Allocation erro? */
143
144 gcry_mpi_clear_highbit (*r, nbits);
145 GNUNET_assert( 0 == gcry_mpi_test_bit (*r, nbits) );
146 ++ctr;
147 } while ( 0 <= gcry_mpi_cmp(*r,n) );
148}
149
150
diff --git a/src/util/crypto_rsa.c b/src/util/crypto_rsa.c
index ab3ce6fe7..4415f20f6 100644
--- a/src/util/crypto_rsa.c
+++ b/src/util/crypto_rsa.c
@@ -400,31 +400,24 @@ GNUNET_CRYPTO_rsa_public_key_decode (const char *buf,
400 * @return the newly created blinding key 400 * @return the newly created blinding key
401 */ 401 */
402static struct RsaBlindingKey * 402static struct RsaBlindingKey *
403rsa_blinding_key_derive (unsigned int len, 403rsa_blinding_key_derive (const struct GNUNET_CRYPTO_RsaPublicKey *pkey,
404 const struct GNUNET_CRYPTO_RsaBlindingKeySecret *bks) 404 const struct GNUNET_CRYPTO_RsaBlindingKeySecret *bks)
405{ 405{
406 char *xts = "Blinding KDF extrator HMAC key"; /* Trusts bks' randomness more */
406 struct RsaBlindingKey *blind; 407 struct RsaBlindingKey *blind;
407 uint8_t buf[len / 8]; 408 gcry_mpi_t n;
408 int rc;
409 size_t rsize;
410 409
411 blind = GNUNET_new (struct RsaBlindingKey); 410 blind = GNUNET_new (struct RsaBlindingKey);
412 /* FIXME: #4483: actually derive key from bks! - Jeff, 411
413 check that you're happy with this!*/ 412 /* Extract the composite n from the RSA public key */
414 GNUNET_assert (GNUNET_YES == 413 GNUNET_assert( 0 == key_from_sexp (&n, pkey->sexp, "rsa", "n") );
415 GNUNET_CRYPTO_kdf (buf, 414 GNUNET_assert( 0 == gcry_mpi_get_flag(n, GCRYMPI_FLAG_OPAQUE) );
416 sizeof (buf), 415
417 "blinding-kdf", 416 GNUNET_CRYPTO_kdf_mod_mpi (&blind->r,
418 strlen ("blinding-kdf"), 417 n,
419 bks, 418 xts, strlen(xts),
420 sizeof (*bks), 419 bks, sizeof(*bks),
421 NULL, 0)); 420 "Blinding KDF");
422 rc = gcry_mpi_scan (&blind->r,
423 GCRYMPI_FMT_USG,
424 (const unsigned char *) buf,
425 sizeof (buf),
426 &rsize);
427 GNUNET_assert (0 == rc);
428 return blind; 421 return blind;
429} 422}
430 423
@@ -538,13 +531,10 @@ unsigned int
538GNUNET_CRYPTO_rsa_public_key_len (const struct GNUNET_CRYPTO_RsaPublicKey *key) 531GNUNET_CRYPTO_rsa_public_key_len (const struct GNUNET_CRYPTO_RsaPublicKey *key)
539{ 532{
540 gcry_mpi_t n; 533 gcry_mpi_t n;
541 int ret;
542 unsigned int rval; 534 unsigned int rval;
543 535
544 ret = key_from_sexp (&n, key->sexp, "rsa", "n"); 536 if (0 != key_from_sexp (&n, key->sexp, "rsa", "n"))
545 if (0 != ret) 537 { /* Not an RSA public key */
546 {
547 /* this is no public RSA key */
548 GNUNET_break (0); 538 GNUNET_break (0);
549 return 0; 539 return 0;
550 } 540 }
@@ -610,91 +600,33 @@ numeric_mpi_alloc_n_print (gcry_mpi_t v,
610 * @param hash initial hash of the message to sign 600 * @param hash initial hash of the message to sign
611 * @param pkey the public key of the signer 601 * @param pkey the public key of the signer
612 * @param rsize If not NULL, the number of bytes actually stored in buffer 602 * @param rsize If not NULL, the number of bytes actually stored in buffer
613 * @return libgcrypt error that to represent an allocation failure
614 */ 603 */
615/* FIXME: exported symbol without proper prefix... */ 604static void
616gcry_error_t
617rsa_full_domain_hash (gcry_mpi_t *r, 605rsa_full_domain_hash (gcry_mpi_t *r,
618 const struct GNUNET_HashCode *hash, 606 const struct GNUNET_HashCode *hash,
619 const struct GNUNET_CRYPTO_RsaPublicKey *pkey, 607 const struct GNUNET_CRYPTO_RsaPublicKey *pkey)
620 size_t *rsize)
621{ 608{
622 unsigned int i; 609 gcry_mpi_t n;
623 unsigned int nbits; 610 char *xts;
624 unsigned int nhashes; 611 size_t xts_len;
625 gcry_error_t rc; 612
626 char *buf; 613 /* Extract the composite n from the RSA public key */
627 size_t buf_len; 614 GNUNET_assert( 0 == key_from_sexp (&n, pkey->sexp, "rsa", "n") );
628 gcry_md_hd_t h; 615 GNUNET_assert( 0 == gcry_mpi_get_flag(n, GCRYMPI_FLAG_OPAQUE) );
629 gcry_md_hd_t h0; 616
630 struct GNUNET_HashCode *hs; 617 /* We key with the public denomination key as a homage to RSA-PSS by *
631 618 * Mihir Bellare and Phillip Rogaway. Doing this lowers the degree *
632 /* Uncomment the following to debug without using the full domain hash */ 619 * of the hypothetical polyomial-time attack on RSA-KTI created by a *
633 /* 620 * polynomial-time one-more forgary attack. Yey seeding! */
634 rc = gcry_mpi_scan (r, 621 xts_len = GNUNET_CRYPTO_rsa_public_key_encode (pkey, &xts);
635 GCRYMPI_FMT_USG, 622
636 (const unsigned char *)hash, 623 GNUNET_CRYPTO_kdf_mod_mpi (r,
637 sizeof(struct GNUNET_HashCode), 624 n,
638 rsize); 625 xts, xts_len,
639 return rc; 626 hash, sizeof(*hash),
640 */ 627 "RSA-FDA FTpsW!");
641 628
642 nbits = GNUNET_CRYPTO_rsa_public_key_len (pkey); 629 GNUNET_free (xts);
643 if (nbits < 512)
644 nbits = 512;
645
646 /* Already almost an HMAC since we consume a hash, so no GCRY_MD_FLAG_HMAC. */
647 rc = gcry_md_open (&h, GCRY_MD_SHA512, 0);
648 if (0 != rc)
649 return rc;
650
651 /* We seed with the public denomination key as a homage to RSA-PSS by *
652 * Mihir Bellare and Phillip Rogaway. Doing this lowers the degree *
653 * of the hypothetical polyomial-time attack on RSA-KTI created by a *
654 * polynomial-time one-more forgary attack. Yey seeding! */
655 buf_len = GNUNET_CRYPTO_rsa_public_key_encode (pkey, &buf);
656 gcry_md_write (h, buf, buf_len);
657 GNUNET_free (buf);
658
659 nhashes = (nbits-1) / (8 * sizeof(struct GNUNET_HashCode)) + 1;
660 hs = GNUNET_new_array (nhashes,
661 struct GNUNET_HashCode);
662 for (i=0; i<nhashes; i++)
663 {
664 gcry_md_write (h, hash, sizeof(struct GNUNET_HashCode));
665 rc = gcry_md_copy (&h0, h);
666 if (0 != rc)
667 {
668 gcry_md_close (h0);
669 break;
670 }
671 gcry_md_putc (h0, i % 256);
672 memcpy (&hs[i],
673 gcry_md_read (h0, GCRY_MD_SHA512),
674 sizeof(struct GNUNET_HashCode));
675 gcry_md_close (h0);
676 }
677 gcry_md_close (h);
678 if (0 != rc)
679 {
680 GNUNET_free (hs);
681 return rc;
682 }
683
684 rc = gcry_mpi_scan (r,
685 GCRYMPI_FMT_USG,
686 (const unsigned char *) hs,
687 nhashes * sizeof(struct GNUNET_HashCode),
688 rsize);
689 GNUNET_free (hs);
690 if (0 != rc)
691 return rc;
692
693 /* Do not allow *r to exceed n or signatures fail to verify unpredictably. *
694 * This happening with gcry_mpi_clear_highbit (*r, nbits-1) so maybe *
695 * gcry_mpi_clear_highbit is broken, but setting the highbit sounds good. */
696 gcry_mpi_set_highbit (*r, nbits-2);
697 return rc;
698} 630}
699 631
700 632
@@ -718,11 +650,8 @@ GNUNET_CRYPTO_rsa_blind (const struct GNUNET_HashCode *hash,
718 gcry_mpi_t ne[2]; 650 gcry_mpi_t ne[2];
719 gcry_mpi_t r_e; 651 gcry_mpi_t r_e;
720 gcry_mpi_t data_r_e; 652 gcry_mpi_t data_r_e;
721 size_t rsize;
722 size_t n; 653 size_t n;
723 gcry_error_t rc;
724 int ret; 654 int ret;
725 unsigned int len;
726 655
727 ret = key_from_sexp (ne, pkey->sexp, "public-key", "ne"); 656 ret = key_from_sexp (ne, pkey->sexp, "public-key", "ne");
728 if (0 != ret) 657 if (0 != ret)
@@ -734,17 +663,8 @@ GNUNET_CRYPTO_rsa_blind (const struct GNUNET_HashCode *hash,
734 return 0; 663 return 0;
735 } 664 }
736 665
737 rc = rsa_full_domain_hash (&data, hash, pkey, &rsize); 666 rsa_full_domain_hash (&data, hash, pkey);
738 if (0 != rc) /* Allocation error in libgcrypt */ 667 bkey = rsa_blinding_key_derive (pkey,
739 {
740 GNUNET_break (0);
741 gcry_mpi_release (ne[0]);
742 gcry_mpi_release (ne[1]);
743 *buffer = NULL;
744 return 0;
745 }
746 len = GNUNET_CRYPTO_rsa_public_key_len (pkey);
747 bkey = rsa_blinding_key_derive (len,
748 bks); 668 bks);
749 r_e = gcry_mpi_new (0); 669 r_e = gcry_mpi_new (0);
750 gcry_mpi_powm (r_e, 670 gcry_mpi_powm (r_e,
@@ -886,13 +806,11 @@ GNUNET_CRYPTO_rsa_sign_fdh (const struct GNUNET_CRYPTO_RsaPrivateKey *key,
886{ 806{
887 struct GNUNET_CRYPTO_RsaPublicKey *pkey; 807 struct GNUNET_CRYPTO_RsaPublicKey *pkey;
888 gcry_mpi_t v = NULL; 808 gcry_mpi_t v = NULL;
889 gcry_error_t rc;
890 struct GNUNET_CRYPTO_RsaSignature *sig; 809 struct GNUNET_CRYPTO_RsaSignature *sig;
891 810
892 pkey = GNUNET_CRYPTO_rsa_private_key_get_public (key); 811 pkey = GNUNET_CRYPTO_rsa_private_key_get_public (key);
893 rc = rsa_full_domain_hash (&v, hash, pkey, NULL); 812 rsa_full_domain_hash (&v, hash, pkey);
894 GNUNET_CRYPTO_rsa_public_key_free (pkey); 813 GNUNET_CRYPTO_rsa_public_key_free (pkey);
895 GNUNET_assert (0 == rc);
896 814
897 sig = rsa_sign_mpi (key, v); 815 sig = rsa_sign_mpi (key, v);
898 gcry_mpi_release (v); 816 gcry_mpi_release (v);
@@ -1034,7 +952,6 @@ GNUNET_CRYPTO_rsa_unblind (struct GNUNET_CRYPTO_RsaSignature *sig,
1034 gcry_mpi_t ubsig; 952 gcry_mpi_t ubsig;
1035 int ret; 953 int ret;
1036 struct GNUNET_CRYPTO_RsaSignature *sret; 954 struct GNUNET_CRYPTO_RsaSignature *sret;
1037 unsigned int len;
1038 955
1039 ret = key_from_sexp (&n, pkey->sexp, "public-key", "n"); 956 ret = key_from_sexp (&n, pkey->sexp, "public-key", "n");
1040 if (0 != ret) 957 if (0 != ret)
@@ -1053,8 +970,7 @@ GNUNET_CRYPTO_rsa_unblind (struct GNUNET_CRYPTO_RsaSignature *sig,
1053 GNUNET_break_op (0); 970 GNUNET_break_op (0);
1054 return NULL; 971 return NULL;
1055 } 972 }
1056 len = GNUNET_CRYPTO_rsa_public_key_len (pkey); 973 bkey = rsa_blinding_key_derive (pkey,
1057 bkey = rsa_blinding_key_derive (len,
1058 bks); 974 bks);
1059 975
1060 r_inv = gcry_mpi_new (0); 976 r_inv = gcry_mpi_new (0);
@@ -1106,8 +1022,7 @@ GNUNET_CRYPTO_rsa_verify (const struct GNUNET_HashCode *hash,
1106 gcry_mpi_t r; 1022 gcry_mpi_t r;
1107 int rc; 1023 int rc;
1108 1024
1109 rc = rsa_full_domain_hash (&r, hash, pkey, NULL); 1025 rsa_full_domain_hash (&r, hash, pkey);
1110 GNUNET_assert (0 == rc); /* Allocation error in libgcrypt */
1111 data = mpi_to_sexp(r); 1026 data = mpi_to_sexp(r);
1112 gcry_mpi_release (r); 1027 gcry_mpi_release (r);
1113 1028
diff --git a/src/util/test_crypto_rsa.c b/src/util/test_crypto_rsa.c
index 2abb008e2..d346bdae8 100644
--- a/src/util/test_crypto_rsa.c
+++ b/src/util/test_crypto_rsa.c
@@ -18,6 +18,7 @@
18 * @file util/test_crypto_rsa.c 18 * @file util/test_crypto_rsa.c
19 * @brief testcase for utility functions for RSA cryptography 19 * @brief testcase for utility functions for RSA cryptography
20 * @author Sree Harsha Totakura <sreeharsha@totakura.in> 20 * @author Sree Harsha Totakura <sreeharsha@totakura.in>
21 * @author Jeffrey Burdges <burdges@gnunet.org>
21 */ 22 */
22#include "platform.h" 23#include "platform.h"
23#include <gcrypt.h> 24#include <gcrypt.h>
@@ -26,13 +27,6 @@
26#define KEY_SIZE 1024 27#define KEY_SIZE 1024
27 28
28 29
29gcry_error_t
30rsa_full_domain_hash (gcry_mpi_t *r,
31 const struct GNUNET_HashCode *hash,
32 const struct GNUNET_CRYPTO_RsaPublicKey *pkey,
33 size_t *rsize);
34
35
36int 30int
37main (int argc, 31main (int argc,
38 char *argv[]) 32 char *argv[])
@@ -50,7 +44,6 @@ main (int argc,
50 struct GNUNET_HashCode hash; 44 struct GNUNET_HashCode hash;
51 char *blind_buf; 45 char *blind_buf;
52 size_t bsize; 46 size_t bsize;
53 gcry_mpi_t v;
54 47
55 GNUNET_log_setup ("test-rsa", "WARNING", NULL); 48 GNUNET_log_setup ("test-rsa", "WARNING", NULL);
56 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, 49 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
@@ -82,14 +75,6 @@ main (int argc,
82 (void) fprintf (stderr, "The above warning is expected.\n"); 75 (void) fprintf (stderr, "The above warning is expected.\n");
83 GNUNET_free (enc); 76 GNUNET_free (enc);
84 77
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
93 /* try ordinary sig first */ 78 /* try ordinary sig first */
94 sig = GNUNET_CRYPTO_rsa_sign_fdh (priv, 79 sig = GNUNET_CRYPTO_rsa_sign_fdh (priv,
95 &hash); 80 &hash);