diff options
author | Christian Grothoff <christian@grothoff.org> | 2014-12-07 23:50:19 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2014-12-07 23:50:19 +0000 |
commit | b65c2c27f8284fde36536cc9b4ff2307b20a1717 (patch) | |
tree | d3c354c3e562ce60e0da69a8f0375b5ebbc15dc5 /src/util/crypto_paillier.c | |
parent | 00ba6aa6e5b4271ed3af3fb98426ff9f74451f31 (diff) | |
download | gnunet-b65c2c27f8284fde36536cc9b4ff2307b20a1717.tar.gz gnunet-b65c2c27f8284fde36536cc9b4ff2307b20a1717.zip |
ensure that a bogus public key cannot send us into an infinite loop
Diffstat (limited to 'src/util/crypto_paillier.c')
-rw-r--r-- | src/util/crypto_paillier.c | 47 |
1 files changed, 30 insertions, 17 deletions
diff --git a/src/util/crypto_paillier.c b/src/util/crypto_paillier.c index 80ad25f1f..c16706dcb 100644 --- a/src/util/crypto_paillier.c +++ b/src/util/crypto_paillier.c | |||
@@ -60,13 +60,15 @@ GNUNET_CRYPTO_paillier_create (struct GNUNET_CRYPTO_PaillierPublicKey *public_ke | |||
60 | gcry_mpi_release (q); | 60 | gcry_mpi_release (q); |
61 | // generate rsa modulus | 61 | // generate rsa modulus |
62 | GNUNET_assert (0 == gcry_prime_generate (&p, GNUNET_CRYPTO_PAILLIER_BITS / 2, 0, NULL, NULL, NULL, | 62 | GNUNET_assert (0 == gcry_prime_generate (&p, GNUNET_CRYPTO_PAILLIER_BITS / 2, 0, NULL, NULL, NULL, |
63 | GCRY_WEAK_RANDOM, 0)); | 63 | GCRY_STRONG_RANDOM, 0)); |
64 | GNUNET_assert (0 == gcry_prime_generate (&q, GNUNET_CRYPTO_PAILLIER_BITS / 2, 0, NULL, NULL, NULL, | 64 | GNUNET_assert (0 == gcry_prime_generate (&q, GNUNET_CRYPTO_PAILLIER_BITS / 2, 0, NULL, NULL, NULL, |
65 | GCRY_WEAK_RANDOM, 0)); | 65 | GCRY_STRONG_RANDOM, 0)); |
66 | } | 66 | } |
67 | while (0 == gcry_mpi_cmp (p, q)); | 67 | while (0 == gcry_mpi_cmp (p, q)); |
68 | gcry_mpi_mul (n, p, q); | 68 | gcry_mpi_mul (n, p, q); |
69 | GNUNET_CRYPTO_mpi_print_unsigned (public_key, sizeof (struct GNUNET_CRYPTO_PaillierPublicKey), n); | 69 | GNUNET_CRYPTO_mpi_print_unsigned (public_key, |
70 | sizeof (struct GNUNET_CRYPTO_PaillierPublicKey), | ||
71 | n); | ||
70 | 72 | ||
71 | // compute phi(n) = (p-1)(q-1) | 73 | // compute phi(n) = (p-1)(q-1) |
72 | gcry_mpi_sub_ui (p, p, 1); | 74 | gcry_mpi_sub_ui (p, p, 1); |
@@ -94,7 +96,7 @@ GNUNET_CRYPTO_paillier_create (struct GNUNET_CRYPTO_PaillierPublicKey *public_ke | |||
94 | * @param m Plaintext to encrypt. | 96 | * @param m Plaintext to encrypt. |
95 | * @param desired_ops How many homomorphic ops the caller intends to use | 97 | * @param desired_ops How many homomorphic ops the caller intends to use |
96 | * @param[out] ciphertext Encrytion of @a plaintext with @a public_key. | 98 | * @param[out] ciphertext Encrytion of @a plaintext with @a public_key. |
97 | * @return guaranteed number of supported homomorphic operations >= 1, | 99 | * @return guaranteed number of supported homomorphic operations >= 1, |
98 | * or desired_ops, in case that is lower, | 100 | * or desired_ops, in case that is lower, |
99 | * or -1 if less than one homomorphic operation is possible | 101 | * or -1 if less than one homomorphic operation is possible |
100 | */ | 102 | */ |
@@ -111,41 +113,52 @@ GNUNET_CRYPTO_paillier_encrypt (const struct GNUNET_CRYPTO_PaillierPublicKey *pu | |||
111 | gcry_mpi_t n; | 113 | gcry_mpi_t n; |
112 | gcry_mpi_t tmp1; | 114 | gcry_mpi_t tmp1; |
113 | gcry_mpi_t tmp2; | 115 | gcry_mpi_t tmp2; |
116 | unsigned int highbit; | ||
114 | 117 | ||
115 | // determine how many operations we could allow, if the other number | 118 | // determine how many operations we could allow, if the other number |
116 | // has the same length. | 119 | // has the same length. |
117 | GNUNET_assert (NULL != (tmp1 = gcry_mpi_set_ui (NULL, 1))); | 120 | GNUNET_assert (NULL != (tmp1 = gcry_mpi_set_ui (NULL, 1))); |
118 | GNUNET_assert (NULL != (tmp2 = gcry_mpi_set_ui (NULL, 2))); | 121 | GNUNET_assert (NULL != (tmp2 = gcry_mpi_set_ui (NULL, 2))); |
119 | gcry_mpi_mul_2exp (tmp1, tmp1, GNUNET_CRYPTO_PAILLIER_BITS); | 122 | gcry_mpi_mul_2exp (tmp1, tmp1, GNUNET_CRYPTO_PAILLIER_BITS); |
120 | 123 | ||
121 | // count number of possible operations | 124 | // count number of possible operations |
122 | // this would be nicer with gcry_mpi_get_nbits, however it does not return | 125 | // this would be nicer with gcry_mpi_get_nbits, however it does not return |
123 | // the BITLENGTH of the given MPI's value, but the bits required | 126 | // the BITLENGTH of the given MPI's value, but the bits required |
124 | // to represent the number as MPI. | 127 | // to represent the number as MPI. |
125 | for (possible_opts = -2; gcry_mpi_cmp (tmp1, m) > 0; possible_opts++) { | 128 | for (possible_opts = -2; gcry_mpi_cmp (tmp1, m) > 0; possible_opts++) |
126 | gcry_mpi_div (tmp1, NULL, tmp1, tmp2, 0); | 129 | gcry_mpi_div (tmp1, NULL, tmp1, tmp2, 0); |
127 | } | ||
128 | gcry_mpi_release (tmp1); | 130 | gcry_mpi_release (tmp1); |
129 | gcry_mpi_release (tmp2); | 131 | gcry_mpi_release (tmp2); |
130 | 132 | ||
131 | if (possible_opts < 1) | 133 | if (possible_opts < 1) |
132 | possible_opts = 0; | 134 | possible_opts = 0; |
133 | //soft-cap by caller | 135 | //soft-cap by caller |
134 | possible_opts = (desired_ops < possible_opts)? desired_ops : possible_opts; | 136 | possible_opts = (desired_ops < possible_opts)? desired_ops : possible_opts; |
135 | 137 | ||
136 | ciphertext->remaining_ops = htonl (possible_opts); | 138 | ciphertext->remaining_ops = htonl (possible_opts); |
137 | 139 | ||
140 | GNUNET_CRYPTO_mpi_scan_unsigned (&n, | ||
141 | public_key, | ||
142 | sizeof (struct GNUNET_CRYPTO_PaillierPublicKey)); | ||
143 | highbit = GNUNET_CRYPTO_PAILLIER_BITS - 1; | ||
144 | while ( (! gcry_mpi_test_bit (n, highbit)) && | ||
145 | (0 != highbit) ) | ||
146 | highbit--; | ||
147 | if (0 == highbit) | ||
148 | { | ||
149 | /* invalid public key */ | ||
150 | GNUNET_break_op (0); | ||
151 | gcry_mpi_release (n); | ||
152 | return GNUNET_SYSERR; | ||
153 | } | ||
138 | GNUNET_assert (0 != (n_square = gcry_mpi_new (0))); | 154 | GNUNET_assert (0 != (n_square = gcry_mpi_new (0))); |
139 | GNUNET_assert (0 != (r = gcry_mpi_new (0))); | 155 | GNUNET_assert (0 != (r = gcry_mpi_new (0))); |
140 | GNUNET_assert (0 != (c = gcry_mpi_new (0))); | 156 | GNUNET_assert (0 != (c = gcry_mpi_new (0))); |
141 | |||
142 | GNUNET_CRYPTO_mpi_scan_unsigned (&n, public_key, sizeof (struct GNUNET_CRYPTO_PaillierPublicKey)); | ||
143 | |||
144 | gcry_mpi_mul (n_square, n, n); | 157 | gcry_mpi_mul (n_square, n, n); |
145 | 158 | ||
146 | // generate r < n | 159 | // generate r < n (without bias) |
147 | do { | 160 | do { |
148 | gcry_mpi_randomize (r, GNUNET_CRYPTO_PAILLIER_BITS, GCRY_WEAK_RANDOM); | 161 | gcry_mpi_randomize (r, highbit + 1, GCRY_STRONG_RANDOM); |
149 | } | 162 | } |
150 | while (gcry_mpi_cmp (r, n) >= 0); | 163 | while (gcry_mpi_cmp (r, n) >= 0); |
151 | 164 | ||
@@ -266,7 +279,7 @@ GNUNET_CRYPTO_paillier_hom_add (const struct GNUNET_CRYPTO_PaillierPublicKey *pu | |||
266 | 279 | ||
267 | 280 | ||
268 | /** | 281 | /** |
269 | * Get the number of remaining supported homomorphic operations. | 282 | * Get the number of remaining supported homomorphic operations. |
270 | * | 283 | * |
271 | * @param c Paillier cipher text. | 284 | * @param c Paillier cipher text. |
272 | * @return the number of remaining homomorphic operations | 285 | * @return the number of remaining homomorphic operations |