Coverage Report

Created: 2020-08-01 06:18

/src/botan/src/lib/math/numbertheory/mod_inv.cpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
* (C) 1999-2011,2016,2018,2019,2020 Jack Lloyd
3
*
4
* Botan is released under the Simplified BSD License (see license.txt)
5
*/
6
7
#include <botan/numthry.h>
8
#include <botan/divide.h>
9
#include <botan/internal/ct_utils.h>
10
#include <botan/internal/mp_core.h>
11
#include <botan/internal/rounding.h>
12
13
namespace Botan {
14
15
/*
16
Sets result to a^-1 * 2^k mod a
17
with n <= k <= 2n
18
Returns k
19
20
"The Montgomery Modular Inverse - Revisited" Çetin Koç, E. Savas
21
https://citeseerx.ist.psu.edu/viewdoc/citations?doi=10.1.1.75.8377
22
23
A const time implementation of this algorithm is described in
24
"Constant Time Modular Inversion" Joppe W. Bos
25
http://www.joppebos.com/files/CTInversion.pdf
26
*/
27
size_t almost_montgomery_inverse(BigInt& result,
28
                                 const BigInt& a,
29
                                 const BigInt& p)
30
0
   {
31
0
   size_t k = 0;
32
0
33
0
   BigInt u = p, v = a, r = 0, s = 1;
34
0
35
0
   while(v > 0)
36
0
      {
37
0
      if(u.is_even())
38
0
         {
39
0
         u >>= 1;
40
0
         s <<= 1;
41
0
         }
42
0
      else if(v.is_even())
43
0
         {
44
0
         v >>= 1;
45
0
         r <<= 1;
46
0
         }
47
0
      else if(u > v)
48
0
         {
49
0
         u -= v;
50
0
         u >>= 1;
51
0
         r += s;
52
0
         s <<= 1;
53
0
         }
54
0
      else
55
0
         {
56
0
         v -= u;
57
0
         v >>= 1;
58
0
         s += r;
59
0
         r <<= 1;
60
0
         }
61
0
62
0
      ++k;
63
0
      }
64
0
65
0
   if(r >= p)
66
0
      {
67
0
      r -= p;
68
0
      }
69
0
70
0
   result = p - r;
71
0
72
0
   return k;
73
0
   }
74
75
BigInt normalized_montgomery_inverse(const BigInt& a, const BigInt& p)
76
0
   {
77
0
   BigInt r;
78
0
   size_t k = almost_montgomery_inverse(r, a, p);
79
0
80
0
   for(size_t i = 0; i != k; ++i)
81
0
      {
82
0
      if(r.is_odd())
83
0
         r += p;
84
0
      r >>= 1;
85
0
      }
86
0
87
0
   return r;
88
0
   }
89
90
namespace {
91
92
BigInt inverse_mod_odd_modulus(const BigInt& n, const BigInt& mod)
93
51.0k
   {
94
51.0k
   // Caller should assure these preconditions:
95
51.0k
   BOTAN_DEBUG_ASSERT(n.is_positive());
96
51.0k
   BOTAN_DEBUG_ASSERT(mod.is_positive());
97
51.0k
   BOTAN_DEBUG_ASSERT(n < mod);
98
51.0k
   BOTAN_DEBUG_ASSERT(mod >= 3 && mod.is_odd());
99
51.0k
100
51.0k
   /*
101
51.0k
   This uses a modular inversion algorithm designed by Niels Möller
102
51.0k
   and implemented in Nettle. The same algorithm was later also
103
51.0k
   adapted to GMP in mpn_sec_invert.
104
51.0k
105
51.0k
   It can be easily implemented in a way that does not depend on
106
51.0k
   secret branches or memory lookups, providing resistance against
107
51.0k
   some forms of side channel attack.
108
51.0k
109
51.0k
   There is also a description of the algorithm in Appendix 5 of "Fast
110
51.0k
   Software Polynomial Multiplication on ARM Processors using the NEON Engine"
111
51.0k
   by Danilo Câmara, Conrado P. L. Gouvêa, Julio López, and Ricardo
112
51.0k
   Dahab in LNCS 8182
113
51.0k
      https://conradoplg.cryptoland.net/files/2010/12/mocrysen13.pdf
114
51.0k
115
51.0k
   Thanks to Niels for creating the algorithm, explaining some things
116
51.0k
   about it, and the reference to the paper.
117
51.0k
   */
118
51.0k
119
51.0k
   const size_t mod_words = mod.sig_words();
120
51.0k
   BOTAN_ASSERT(mod_words > 0, "Not empty");
121
51.0k
122
51.0k
   secure_vector<word> tmp_mem(5*mod_words);
123
51.0k
124
51.0k
   word* v_w = &tmp_mem[0];
125
51.0k
   word* u_w = &tmp_mem[1*mod_words];
126
51.0k
   word* b_w = &tmp_mem[2*mod_words];
127
51.0k
   word* a_w = &tmp_mem[3*mod_words];
128
51.0k
   word* mp1o2 = &tmp_mem[4*mod_words];
129
51.0k
130
51.0k
   CT::poison(tmp_mem.data(), tmp_mem.size());
131
51.0k
132
51.0k
   copy_mem(a_w, n.data(), std::min(n.size(), mod_words));
133
51.0k
   copy_mem(b_w, mod.data(), std::min(mod.size(), mod_words));
134
51.0k
   u_w[0] = 1;
135
51.0k
   // v_w = 0
136
51.0k
137
51.0k
   // compute (mod + 1) / 2 which [because mod is odd] is equal to
138
51.0k
   // (mod / 2) + 1
139
51.0k
   copy_mem(mp1o2, mod.data(), std::min(mod.size(), mod_words));
140
51.0k
   bigint_shr1(mp1o2, mod_words, 0, 1);
141
51.0k
   word carry = bigint_add2_nc(mp1o2, mod_words, u_w, 1);
142
51.0k
   BOTAN_ASSERT_NOMSG(carry == 0);
143
51.0k
144
51.0k
   // Only n.bits() + mod.bits() iterations are required, but avoid leaking the size of n
145
51.0k
   const size_t execs = 2 * mod.bits();
146
51.0k
147
43.0M
   for(size_t i = 0; i != execs; ++i)
148
42.9M
      {
149
42.9M
      const word odd_a = a_w[0] & 1;
150
42.9M
151
42.9M
      //if(odd_a) a -= b
152
42.9M
      word underflow = bigint_cnd_sub(odd_a, a_w, b_w, mod_words);
153
42.9M
154
42.9M
      //if(underflow) { b -= a; a = abs(a); swap(u, v); }
155
42.9M
      bigint_cnd_add(underflow, b_w, a_w, mod_words);
156
42.9M
      bigint_cnd_abs(underflow, a_w, mod_words);
157
42.9M
      bigint_cnd_swap(underflow, u_w, v_w, mod_words);
158
42.9M
159
42.9M
      // a >>= 1
160
42.9M
      bigint_shr1(a_w, mod_words, 0, 1);
161
42.9M
162
42.9M
      //if(odd_a) u -= v;
163
42.9M
      word borrow = bigint_cnd_sub(odd_a, u_w, v_w, mod_words);
164
42.9M
165
42.9M
      // if(borrow) u += p
166
42.9M
      bigint_cnd_add(borrow, u_w, mod.data(), mod_words);
167
42.9M
168
42.9M
      const word odd_u = u_w[0] & 1;
169
42.9M
170
42.9M
      // u >>= 1
171
42.9M
      bigint_shr1(u_w, mod_words, 0, 1);
172
42.9M
173
42.9M
      //if(odd_u) u += mp1o2;
174
42.9M
      bigint_cnd_add(odd_u, u_w, mp1o2, mod_words);
175
42.9M
      }
176
51.0k
177
51.0k
   auto a_is_0 = CT::Mask<word>::set();
178
393k
   for(size_t i = 0; i != mod_words; ++i)
179
342k
      a_is_0 &= CT::Mask<word>::is_zero(a_w[i]);
180
51.0k
181
51.0k
   auto b_is_1 = CT::Mask<word>::is_equal(b_w[0], 1);
182
342k
   for(size_t i = 1; i != mod_words; ++i)
183
291k
      b_is_1 &= CT::Mask<word>::is_zero(b_w[i]);
184
51.0k
185
51.0k
   BOTAN_ASSERT(a_is_0.is_set(), "A is zero");
186
51.0k
187
51.0k
   // if b != 1 then gcd(n,mod) > 1 and inverse does not exist
188
51.0k
   // in which case zero out the result to indicate this
189
51.0k
   (~b_is_1).if_set_zero_out(v_w, mod_words);
190
51.0k
191
51.0k
   /*
192
51.0k
   * We've placed the result in the lowest words of the temp buffer.
193
51.0k
   * So just clear out the other values and then give that buffer to a
194
51.0k
   * BigInt.
195
51.0k
   */
196
51.0k
   clear_mem(&tmp_mem[mod_words], 4*mod_words);
197
51.0k
198
51.0k
   CT::unpoison(tmp_mem.data(), tmp_mem.size());
199
51.0k
200
51.0k
   BigInt r;
201
51.0k
   r.swap_reg(tmp_mem);
202
51.0k
   return r;
203
51.0k
   }
204
205
BigInt inverse_mod_pow2(const BigInt& a1, size_t k)
206
1.23k
   {
207
1.23k
   /*
208
1.23k
   * From "A New Algorithm for Inversion mod p^k" by Çetin Kaya Koç
209
1.23k
   * https://eprint.iacr.org/2017/411.pdf sections 5 and 7.
210
1.23k
   */
211
1.23k
212
1.23k
   if(a1.is_even())
213
0
      return 0;
214
1.23k
215
1.23k
   BigInt a = a1;
216
1.23k
   a.mask_bits(k);
217
1.23k
218
1.23k
   BigInt b = 1;
219
1.23k
   BigInt X = 0;
220
1.23k
   BigInt newb;
221
1.23k
222
1.23k
   const size_t a_words = a.sig_words();
223
1.23k
224
1.23k
   X.grow_to(round_up(k, BOTAN_MP_WORD_BITS) / BOTAN_MP_WORD_BITS);
225
1.23k
   b.grow_to(a_words);
226
1.23k
227
1.23k
   /*
228
1.23k
   Hide the exact value of k. k is anyway known to word length
229
1.23k
   granularity because of the length of a, so no point in doing more
230
1.23k
   than this.
231
1.23k
   */
232
1.23k
   const size_t iter = round_up(k, BOTAN_MP_WORD_BITS);
233
1.23k
234
696k
   for(size_t i = 0; i != iter; ++i)
235
695k
      {
236
695k
      const bool b0 = b.get_bit(0);
237
695k
      X.conditionally_set_bit(i, b0);
238
695k
      newb = b - a;
239
695k
      b.ct_cond_assign(b0, newb);
240
695k
      b >>= 1;
241
695k
      }
242
1.23k
243
1.23k
   X.mask_bits(k);
244
1.23k
   X.const_time_unpoison();
245
1.23k
   return X;
246
1.23k
   }
247
248
}
249
250
BigInt inverse_mod(const BigInt& n, const BigInt& mod)
251
51.2k
   {
252
51.2k
   if(mod.is_zero())
253
0
      throw BigInt::DivideByZero();
254
51.2k
   if(mod.is_negative() || n.is_negative())
255
0
      throw Invalid_Argument("inverse_mod: arguments must be non-negative");
256
51.2k
   if(n.is_zero() || (n.is_even() && mod.is_even()))
257
177
      return 0;
258
51.0k
259
51.0k
   if(mod.is_odd())
260
50.3k
      {
261
50.3k
      /*
262
50.3k
      Fastpath for common case. This leaks information if n > mod
263
50.3k
      but we don't guarantee const time behavior in that case.
264
50.3k
      */
265
50.3k
      if(n < mod)
266
50.3k
         return inverse_mod_odd_modulus(n, mod);
267
60
      else
268
60
         return inverse_mod_odd_modulus(ct_modulo(n, mod), mod);
269
694
      }
270
694
271
694
   const size_t mod_lz = low_zero_bits(mod);
272
694
   BOTAN_ASSERT_NOMSG(mod_lz > 0);
273
694
   const size_t mod_bits = mod.bits();
274
694
   BOTAN_ASSERT_NOMSG(mod_bits > mod_lz);
275
694
276
694
   if(mod_lz == mod_bits - 1)
277
54
      {
278
54
      // In this case we are performing an inversion modulo 2^k
279
54
      return inverse_mod_pow2(n, mod_lz);
280
54
      }
281
640
282
640
   /*
283
640
   * In this case we are performing an inversion modulo 2^k*o for
284
640
   * some k > 1 and some odd (not necessarily prime) integer.
285
640
   * Compute the inversions modulo 2^k and modulo o, then combine them
286
640
   * using CRT, which is possible because 2^k and o are relatively prime.
287
640
   */
288
640
289
640
   const BigInt o = mod >> mod_lz;
290
640
   const BigInt n_redc = ct_modulo(n, o);
291
640
   const BigInt inv_o = inverse_mod_odd_modulus(n_redc, o);
292
640
   const BigInt inv_2k = inverse_mod_pow2(n, mod_lz);
293
640
294
640
   // No modular inverse in this case:
295
640
   if(inv_o == 0 || inv_2k == 0)
296
103
      return 0;
297
537
298
537
   const BigInt m2k = BigInt::power_of_2(mod_lz);
299
537
   // Compute the CRT parameter
300
537
   const BigInt c = inverse_mod_pow2(o, mod_lz);
301
537
302
537
   // Compute h = c*(inv_2k-inv_o) mod 2^k
303
537
   BigInt h = c * (inv_2k - inv_o);
304
537
   const bool h_neg = h.is_negative();
305
537
   h.set_sign(BigInt::Positive);
306
537
   h.mask_bits(mod_lz);
307
537
   const bool h_nonzero = h.is_nonzero();
308
537
   h.ct_cond_assign(h_nonzero && h_neg, m2k - h);
309
537
310
537
   // Return result inv_o + h * o
311
537
   h *= o;
312
537
   h += inv_o;
313
537
   return h;
314
537
   }
315
316
// Deprecated forwarding functions:
317
BigInt inverse_euclid(const BigInt& x, const BigInt& modulus)
318
0
   {
319
0
   return inverse_mod(x, modulus);
320
0
   }
321
322
BigInt ct_inverse_mod_odd_modulus(const BigInt& n, const BigInt& mod)
323
0
   {
324
0
   return inverse_mod_odd_modulus(n, mod);
325
0
   }
326
327
word monty_inverse(word a)
328
87.2k
   {
329
87.2k
   if(a % 2 == 0)
330
0
      throw Invalid_Argument("monty_inverse only valid for odd integers");
331
87.2k
332
87.2k
   /*
333
87.2k
   * From "A New Algorithm for Inversion mod p^k" by Çetin Kaya Koç
334
87.2k
   * https://eprint.iacr.org/2017/411.pdf sections 5 and 7.
335
87.2k
   */
336
87.2k
337
87.2k
   word b = 1;
338
87.2k
   word r = 0;
339
87.2k
340
5.67M
   for(size_t i = 0; i != BOTAN_MP_WORD_BITS; ++i)
341
5.58M
      {
342
5.58M
      const word bi = b % 2;
343
5.58M
      r >>= 1;
344
5.58M
      r += bi << (BOTAN_MP_WORD_BITS - 1);
345
5.58M
346
5.58M
      b -= a * bi;
347
5.58M
      b >>= 1;
348
5.58M
      }
349
87.2k
350
87.2k
   // Now invert in addition space
351
87.2k
   r = (MP_WORD_MAX - r) + 1;
352
87.2k
353
87.2k
   return r;
354
87.2k
   }
355
356
}