Coverage Report

Created: 2026-06-07 07:04

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/botan/src/lib/math/numbertheory/numthry.cpp
Line
Count
Source
1
/*
2
* Number Theory Functions
3
* (C) 1999-2011,2016,2018,2019 Jack Lloyd
4
* (C) 2007,2008 Falko Strenzke, FlexSecure GmbH
5
*
6
* Botan is released under the Simplified BSD License (see license.txt)
7
*/
8
9
#include <botan/numthry.h>
10
11
#include <botan/rng.h>
12
#include <botan/internal/barrett.h>
13
#include <botan/internal/ct_utils.h>
14
#include <botan/internal/divide.h>
15
#include <botan/internal/monty.h>
16
#include <botan/internal/monty_exp.h>
17
#include <botan/internal/mp_core.h>
18
#include <botan/internal/primality.h>
19
#include <algorithm>
20
21
namespace Botan {
22
23
/*
24
* Tonelli-Shanks algorithm
25
*/
26
0
BigInt sqrt_modulo_prime(const BigInt& a, const BigInt& p) {
27
0
   BOTAN_ARG_CHECK(p > 1, "invalid prime");
28
0
   BOTAN_ARG_CHECK(a < p, "value to solve for must be less than p");
29
0
   BOTAN_ARG_CHECK(a >= 0, "value to solve for must not be negative");
30
31
   // some very easy cases
32
0
   if(p == 2 || a <= 1) {
33
0
      return a;
34
0
   }
35
36
0
   BOTAN_ARG_CHECK(p.is_odd(), "invalid prime");
37
38
0
   if(jacobi(a, p) != 1) {  // not a quadratic residue
39
0
      return BigInt::from_s32(-1);
40
0
   }
41
42
0
   auto mod_p = Barrett_Reduction::for_public_modulus(p);
43
0
   auto monty_p = std::make_shared<Montgomery_Params>(p, mod_p);
44
45
   // If p == 3 (mod 4) there is a simple solution
46
0
   if(p % 4 == 3) {
47
0
      return monty_exp_vartime(monty_p, a, ((p + 1) >> 2)).value();
48
0
   }
49
50
   // Otherwise we have to use Shanks-Tonelli
51
0
   size_t s = low_zero_bits(p - 1);
52
0
   BigInt q = p >> s;
53
54
0
   q -= 1;
55
0
   q >>= 1;
56
57
0
   BigInt r = monty_exp_vartime(monty_p, a, q).value();
58
0
   BigInt n = mod_p.multiply(a, mod_p.square(r));
59
0
   r = mod_p.multiply(r, a);
60
61
0
   if(n == 1) {
62
0
      return r;
63
0
   }
64
65
   // find random quadratic nonresidue z
66
0
   word z = 2;
67
0
   for(;;) {
68
0
      if(jacobi(BigInt::from_word(z), p) == -1) {  // found one
69
0
         break;
70
0
      }
71
72
0
      z += 1;  // try next z
73
74
      /*
75
      * The expected number of tests to find a non-residue modulo a
76
      * prime is 2. If we have not found one after 256 then almost
77
      * certainly we have been given a non-prime p.
78
      */
79
0
      if(z >= 256) {
80
0
         return BigInt::from_s32(-1);
81
0
      }
82
0
   }
83
84
0
   BigInt c = monty_exp_vartime(monty_p, BigInt::from_word(z), (q << 1) + 1).value();
85
86
0
   while(n > 1) {
87
0
      q = n;
88
89
0
      size_t i = 0;
90
0
      while(q != 1) {
91
0
         q = mod_p.square(q);
92
0
         ++i;
93
94
0
         if(i >= s) {
95
0
            return BigInt::from_s32(-1);
96
0
         }
97
0
      }
98
99
0
      BOTAN_ASSERT_NOMSG(s >= (i + 1));  // No underflow!
100
0
      c = monty_exp_vartime(monty_p, c, BigInt::power_of_2(s - i - 1)).value();
101
0
      r = mod_p.multiply(r, c);
102
0
      c = mod_p.square(c);
103
0
      n = mod_p.multiply(n, c);
104
105
      // s decreases as the algorithm proceeds
106
0
      BOTAN_ASSERT_NOMSG(s >= i);
107
0
      s = i;
108
0
   }
109
110
0
   return r;
111
0
}
112
113
/*
114
* Calculate the Jacobi symbol
115
*/
116
348
int32_t jacobi(const BigInt& a, const BigInt& n) {
117
348
   if(n.is_even() || n < 2) {
118
9
      throw Invalid_Argument("jacobi: second argument must be odd and > 1");
119
9
   }
120
121
339
   BigInt x = a % n;
122
339
   BigInt y = n;
123
339
   int32_t J = 1;
124
125
64.6k
   while(y > 1) {
126
64.4k
      x %= y;
127
64.4k
      if(x > y / 2) {
128
29.4k
         x = y - x;
129
29.4k
         if(y % 4 == 3) {
130
15.0k
            J = -J;
131
15.0k
         }
132
29.4k
      }
133
64.4k
      if(x.is_zero()) {
134
91
         return 0;
135
91
      }
136
137
64.3k
      size_t shifts = low_zero_bits(x);
138
64.3k
      x >>= shifts;
139
64.3k
      if(shifts % 2) {
140
20.6k
         word y_mod_8 = y % 8;
141
20.6k
         if(y_mod_8 == 3 || y_mod_8 == 5) {
142
10.3k
            J = -J;
143
10.3k
         }
144
20.6k
      }
145
146
64.3k
      if(x % 4 == 3 && y % 4 == 3) {
147
16.5k
         J = -J;
148
16.5k
      }
149
64.3k
      std::swap(x, y);
150
64.3k
   }
151
248
   return J;
152
339
}
153
154
/*
155
* Square a BigInt
156
*/
157
169
BigInt square(const BigInt& x) {
158
169
   BigInt z = x;
159
169
   secure_vector<word> ws;
160
169
   z.square(ws);
161
169
   return z;
162
169
}
163
164
/*
165
* Return the number of 0 bits at the end of n
166
*/
167
64.5k
size_t low_zero_bits(const BigInt& n) {
168
64.5k
   size_t low_zero = 0;
169
170
64.5k
   auto seen_nonempty_word = CT::Mask<word>::cleared();
171
172
3.09M
   for(size_t i = 0; i != n.size(); ++i) {
173
3.03M
      const word x = n.word_at(i);
174
175
      // ctz(0) will return sizeof(word)
176
3.03M
      const size_t tz_x = ctz(x);
177
178
      // if x > 0 we want to count tz_x in total but not any
179
      // further words, so set the mask after the addition
180
3.03M
      low_zero += seen_nonempty_word.if_not_set_return(tz_x);
181
182
3.03M
      seen_nonempty_word |= CT::Mask<word>::expand(x);
183
3.03M
   }
184
185
   // if we saw no words with x > 0 then n == 0 and the value we have
186
   // computed is meaningless. Instead return BigInt::zero() in that case.
187
64.5k
   return static_cast<size_t>(seen_nonempty_word.if_set_return(low_zero));
188
64.5k
}
189
190
/*
191
* Calculate the GCD in constant time
192
*/
193
1.13k
BigInt gcd(const BigInt& a, const BigInt& b) {
194
1.13k
   if(a.is_zero()) {
195
43
      return abs(b);
196
43
   }
197
1.08k
   if(b.is_zero()) {
198
61
      return abs(a);
199
61
   }
200
201
1.02k
   const size_t sz = std::max(a.sig_words(), b.sig_words());
202
1.02k
   auto u = BigInt::with_capacity(sz);
203
1.02k
   auto v = BigInt::with_capacity(sz);
204
1.02k
   u += a;
205
1.02k
   v += b;
206
207
1.02k
   CT::poison_all(u, v);
208
209
1.02k
   u.set_sign(BigInt::Positive);
210
1.02k
   v.set_sign(BigInt::Positive);
211
212
   // In the worst case we have two fully populated big ints. After right
213
   // shifting so many times, we'll have reached the result for sure.
214
1.02k
   const size_t loop_cnt = u.bits() + v.bits();
215
216
1.02k
   using WordMask = CT::Mask<word>;
217
218
   // This temporary is big enough to hold all intermediate results of the
219
   // algorithm. No reallocation will happen during the loop.
220
   // Note however, that `ct_cond_assign()` will invalidate the 'sig_words'
221
   // cache, which _does not_ shrink the capacity of the underlying buffer.
222
1.02k
   auto tmp = BigInt::with_capacity(sz);
223
1.02k
   size_t factors_of_two = 0;
224
1.40M
   for(size_t i = 0; i != loop_cnt; ++i) {
225
1.40M
      auto both_odd = WordMask::expand(u.is_odd()) & WordMask::expand(v.is_odd());
226
227
      // Subtract the smaller from the larger if both are odd
228
1.40M
      auto u_gt_v = WordMask::expand(bigint_cmp(u._data(), u.size(), v._data(), v.size()) > 0);
229
1.40M
      bigint_sub_abs(tmp.mutable_data(), u._data(), sz, v._data(), sz);
230
1.40M
      u.ct_cond_assign((u_gt_v & both_odd).as_bool(), tmp);
231
1.40M
      v.ct_cond_assign((~u_gt_v & both_odd).as_bool(), tmp);
232
233
1.40M
      const auto u_is_even = WordMask::expand(u.is_even());
234
1.40M
      const auto v_is_even = WordMask::expand(v.is_even());
235
1.40M
      BOTAN_DEBUG_ASSERT((u_is_even | v_is_even).as_bool());
236
237
      // When both are even, we're going to eliminate a factor of 2.
238
      // We have to reapply this factor to the final result.
239
1.40M
      factors_of_two += (u_is_even & v_is_even).if_set_return(1);
240
241
      // remove one factor of 2, if u is even
242
1.40M
      bigint_shr2(tmp.mutable_data(), u._data(), sz, 1);
243
1.40M
      u.ct_cond_assign(u_is_even.as_bool(), tmp);
244
245
      // remove one factor of 2, if v is even
246
1.40M
      bigint_shr2(tmp.mutable_data(), v._data(), sz, 1);
247
1.40M
      v.ct_cond_assign(v_is_even.as_bool(), tmp);
248
1.40M
   }
249
250
   // The GCD (without factors of two) is either in u or v, the other one is
251
   // zero. The non-zero variable _must_ be odd, because all factors of two were
252
   // removed in the loop iterations above.
253
1.02k
   BOTAN_DEBUG_ASSERT(u.is_zero() || v.is_zero());
254
1.02k
   BOTAN_DEBUG_ASSERT(u.is_odd() || v.is_odd());
255
256
   // make sure that the GCD (without factors of two) is in u
257
1.02k
   u.ct_cond_assign(u.is_even() /* .is_zero() would not be constant time */, v);
258
259
   // re-apply the factors of two
260
1.02k
   u.ct_shift_left(factors_of_two);
261
262
1.02k
   CT::unpoison_all(u, v);
263
264
1.02k
   return u;
265
1.08k
}
266
267
/*
268
* Calculate the LCM
269
*/
270
240
BigInt lcm(const BigInt& a, const BigInt& b) {
271
240
   if(a == b) {
272
5
      return a;
273
5
   }
274
275
235
   auto ab = a * b;
276
235
   ab.set_sign(BigInt::Positive);  // ignore the signs of a & b
277
235
   const auto g = gcd(a, b);
278
235
   return ct_divide(ab, g);
279
240
}
280
281
/*
282
* Modular Exponentiation
283
*/
284
909
BigInt power_mod(const BigInt& base, const BigInt& exp, const BigInt& mod) {
285
909
   if(mod.is_negative() || mod == 1) {
286
14
      return BigInt::zero();
287
14
   }
288
289
895
   if(base.is_zero() || mod.is_zero()) {
290
42
      if(exp.is_zero()) {
291
3
         return BigInt::one();
292
3
      }
293
39
      return BigInt::zero();
294
42
   }
295
296
853
   auto reduce_mod = Barrett_Reduction::for_secret_modulus(mod);
297
298
853
   const size_t exp_bits = exp.bits();
299
300
853
   if(mod.is_odd()) {
301
651
      auto monty_params = std::make_shared<Montgomery_Params>(mod, reduce_mod);
302
651
      return monty_exp(monty_params, ct_modulo(base, mod), exp, exp_bits).value();
303
651
   }
304
305
   /*
306
   Support for even modulus is just a convenience and not considered
307
   cryptographically important, so this implementation is slow ...
308
   */
309
202
   BigInt accum = BigInt::one();
310
202
   BigInt g = ct_modulo(base, mod);
311
202
   BigInt t;
312
313
14.7k
   for(size_t i = 0; i != exp_bits; ++i) {
314
14.5k
      t = reduce_mod.multiply(g, accum);
315
14.5k
      g = reduce_mod.square(g);
316
14.5k
      accum.ct_cond_assign(exp.get_bit(i), t);
317
14.5k
   }
318
202
   return accum;
319
853
}
320
321
279
BigInt is_perfect_square(const BigInt& C) {
322
279
   if(C < 1) {
323
5
      throw Invalid_Argument("is_perfect_square requires C >= 1");
324
5
   }
325
274
   if(C == 1) {
326
3
      return BigInt::one();
327
3
   }
328
329
271
   const size_t n = C.bits();
330
271
   const size_t m = (n + 1) / 2;
331
271
   const BigInt B = C + BigInt::power_of_2(m);
332
333
271
   BigInt X = BigInt::power_of_2(m) - 1;
334
271
   BigInt X2 = (X * X);
335
336
1.52k
   for(;;) {
337
1.52k
      X = (X2 + C) / (2 * X);
338
1.52k
      X2 = (X * X);
339
340
1.52k
      if(X2 < B) {
341
271
         break;
342
271
      }
343
1.52k
   }
344
345
271
   if(X2 == C) {
346
6
      return X;
347
265
   } else {
348
265
      return BigInt::zero();
349
265
   }
350
271
}
351
352
/*
353
* Test for primality using Miller-Rabin
354
*/
355
0
bool is_prime(const BigInt& n, RandomNumberGenerator& rng, size_t prob, bool is_random) {
356
0
   if(n == 2) {
357
0
      return true;
358
0
   }
359
0
   if(n <= 1 || n.is_even()) {
360
0
      return false;
361
0
   }
362
363
0
   const size_t n_bits = n.bits();
364
365
   // Fast path testing for small numbers (<= 65521)
366
0
   if(n_bits <= 16) {
367
0
      const uint16_t num = static_cast<uint16_t>(n.word_at(0));
368
369
0
      return std::binary_search(PRIMES, PRIMES + PRIME_TABLE_SIZE, num);
370
0
   }
371
372
0
   auto mod_n = Barrett_Reduction::for_secret_modulus(n);
373
374
0
   if(rng.is_seeded()) {
375
0
      const size_t t = miller_rabin_test_iterations(n_bits, prob, is_random);
376
377
0
      if(is_miller_rabin_probable_prime(n, mod_n, rng, t) == false) {
378
0
         return false;
379
0
      }
380
381
0
      if(is_random) {
382
0
         return true;
383
0
      } else {
384
0
         return is_lucas_probable_prime(n, mod_n);
385
0
      }
386
0
   } else {
387
0
      return is_bailie_psw_probable_prime(n, mod_n);
388
0
   }
389
0
}
390
391
}  // namespace Botan