• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

randombit / botan / 5123321399

30 May 2023 04:06PM UTC coverage: 92.213% (+0.004%) from 92.209%
5123321399

Pull #3558

github

web-flow
Merge dd72f7389 into 057bcbc35
Pull Request #3558: Add braces around all if/else statements

75602 of 81986 relevant lines covered (92.21%)

11859779.3 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

96.32
/src/lib/math/numbertheory/numthry.cpp
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/reducer.h>
12
#include <botan/rng.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
namespace {
24

25
void sub_abs(BigInt& z, const BigInt& x, const BigInt& y) {
5,361,805✔
26
   const size_t x_sw = x.sig_words();
5,361,805✔
27
   const size_t y_sw = y.sig_words();
5,361,805✔
28
   z.resize(std::max(x_sw, y_sw));
5,418,579✔
29

30
   bigint_sub_abs(z.mutable_data(), x.data(), x_sw, y.data(), y_sw);
5,361,805✔
31
}
5,361,805✔
32

33
}  // namespace
34

35
/*
36
* Tonelli-Shanks algorithm
37
*/
38
BigInt sqrt_modulo_prime(const BigInt& a, const BigInt& p) {
6,788✔
39
   BOTAN_ARG_CHECK(p > 1, "invalid prime");
6,788✔
40
   BOTAN_ARG_CHECK(a < p, "value to solve for must be less than p");
6,788✔
41
   BOTAN_ARG_CHECK(a >= 0, "value to solve for must not be negative");
6,788✔
42

43
   // some very easy cases
44
   if(p == 2 || a <= 1) {
13,574✔
45
      return a;
6,791✔
46
   }
47

48
   BOTAN_ARG_CHECK(p.is_odd(), "invalid prime");
13,570✔
49

50
   if(jacobi(a, p) != 1) {  // not a quadratic residue
6,785✔
51
      return BigInt::from_s32(-1);
2,657✔
52
   }
53

54
   Modular_Reducer mod_p(p);
4,128✔
55
   auto monty_p = std::make_shared<Montgomery_Params>(p, mod_p);
4,128✔
56

57
   if(p % 4 == 3)  // The easy case
4,128✔
58
   {
59
      return monty_exp_vartime(monty_p, a, ((p + 1) >> 2));
18,245✔
60
   }
61

62
   // Otherwise we have to use Shanks-Tonelli
63
   size_t s = low_zero_bits(p - 1);
479✔
64
   BigInt q = p >> s;
479✔
65

66
   q -= 1;
479✔
67
   q >>= 1;
479✔
68

69
   BigInt r = monty_exp_vartime(monty_p, a, q);
479✔
70
   BigInt n = mod_p.multiply(a, mod_p.square(r));
479✔
71
   r = mod_p.multiply(r, a);
479✔
72

73
   if(n == 1) {
479✔
74
      return r;
10✔
75
   }
76

77
   // find random quadratic nonresidue z
78
   word z = 2;
79
   for(;;) {
4,826✔
80
      if(jacobi(BigInt::from_word(z), p) == -1) {  // found one
9,652✔
81
         break;
82
      }
83

84
      z += 1;  // try next z
4,358✔
85

86
      /*
87
      * The expected number of tests to find a non-residue modulo a
88
      * prime is 2. If we have not found one after 256 then almost
89
      * certainly we have been given a non-prime p.
90
      */
91
      if(z >= 256) {
4,358✔
92
         return BigInt::from_s32(-1);
1✔
93
      }
94
   }
95

96
   BigInt c = monty_exp_vartime(monty_p, BigInt::from_word(z), (q << 1) + 1);
2,808✔
97

98
   while(n > 1) {
21,607✔
99
      q = n;
21,145✔
100

101
      size_t i = 0;
21,145✔
102
      while(q != 1) {
1,037,063✔
103
         q = mod_p.square(q);
1,015,924✔
104
         ++i;
1,015,924✔
105

106
         if(i >= s) {
1,015,924✔
107
            return BigInt::from_s32(-1);
6✔
108
         }
109
      }
110

111
      BOTAN_ASSERT_NOMSG(s >= (i + 1));  // No underflow!
21,139✔
112
      c = monty_exp_vartime(monty_p, c, BigInt::power_of_2(s - i - 1));
84,556✔
113
      r = mod_p.multiply(r, c);
21,139✔
114
      c = mod_p.square(c);
21,139✔
115
      n = mod_p.multiply(n, c);
21,139✔
116

117
      // s decreases as the algorithm proceeds
118
      BOTAN_ASSERT_NOMSG(s >= i);
21,139✔
119
      s = i;
120
   }
121

122
   return r;
468✔
123
}
9,221✔
124

125
/*
126
* Calculate the Jacobi symbol
127
*/
128
int32_t jacobi(const BigInt& a, const BigInt& n) {
109,699✔
129
   if(n.is_even() || n < 2) {
329,097✔
130
      throw Invalid_Argument("jacobi: second argument must be odd and > 1");
×
131
   }
132

133
   BigInt x = a % n;
109,699✔
134
   BigInt y = n;
109,699✔
135
   int32_t J = 1;
109,699✔
136

137
   while(y > 1) {
1,129,529✔
138
      x %= y;
926,778✔
139
      if(x > y / 2) {
2,780,334✔
140
         x = y - x;
402,261✔
141
         if(y % 4 == 3) {
402,261✔
142
            J = -J;
196,350✔
143
         }
144
      }
145
      if(x.is_zero()) {
1,329,039✔
146
         return 0;
147
      }
148

149
      size_t shifts = low_zero_bits(x);
910,131✔
150
      x >>= shifts;
910,131✔
151
      if(shifts % 2) {
910,131✔
152
         word y_mod_8 = y % 8;
266,611✔
153
         if(y_mod_8 == 3 || y_mod_8 == 5) {
266,611✔
154
            J = -J;
139,776✔
155
         }
156
      }
157

158
      if(x % 4 == 3 && y % 4 == 3) {
910,131✔
159
         J = -J;
203,161✔
160
      }
161
      std::swap(x, y);
1,019,830✔
162
   }
163
   return J;
164
}
202,773✔
165

166
/*
167
* Square a BigInt
168
*/
169
BigInt square(const BigInt& x) {
2,961,150✔
170
   BigInt z = x;
2,961,150✔
171
   secure_vector<word> ws;
2,961,150✔
172
   z.square(ws);
2,961,150✔
173
   return z;
2,961,150✔
174
}
2,961,150✔
175

176
/*
177
* Return the number of 0 bits at the end of n
178
*/
179
size_t low_zero_bits(const BigInt& n) {
1,155,592✔
180
   size_t low_zero = 0;
1,155,592✔
181

182
   auto seen_nonempty_word = CT::Mask<word>::cleared();
1,155,592✔
183

184
   for(size_t i = 0; i != n.size(); ++i) {
12,366,428✔
185
      const word x = n.word_at(i);
11,210,836✔
186

187
      // ctz(0) will return sizeof(word)
188
      const size_t tz_x = ctz(x);
11,210,836✔
189

190
      // if x > 0 we want to count tz_x in total but not any
191
      // further words, so set the mask after the addition
192
      low_zero += seen_nonempty_word.if_not_set_return(tz_x);
11,210,836✔
193

194
      seen_nonempty_word |= CT::Mask<word>::expand(x);
11,210,836✔
195
   }
196

197
   // if we saw no words with x > 0 then n == 0 and the value we have
198
   // computed is meaningless. Instead return BigInt::zero() in that case.
199
   return seen_nonempty_word.if_set_return(low_zero);
1,155,592✔
200
}
201

202
namespace {
203

204
size_t safegcd_loop_bound(size_t f_bits, size_t g_bits) {
22,057✔
205
   const size_t d = std::max(f_bits, g_bits);
22,057✔
206
   return 4 + 3 * d;
22,057✔
207
}
208

209
}  // namespace
210

211
/*
212
* Calculate the GCD
213
*/
214
BigInt gcd(const BigInt& a, const BigInt& b) {
22,065✔
215
   if(a.is_zero()) {
23,797✔
216
      return abs(b);
4✔
217
   }
218
   if(b.is_zero()) {
42,143✔
219
      return abs(a);
2✔
220
   }
221
   if(a == 1 || b == 1) {
44,116✔
222
      return BigInt::one();
2✔
223
   }
224

225
   // See https://gcd.cr.yp.to/safegcd-20190413.pdf fig 1.2
226

227
   BigInt f = a;
22,057✔
228
   BigInt g = b;
22,057✔
229
   f.const_time_poison();
22,057✔
230
   g.const_time_poison();
22,057✔
231

232
   f.set_sign(BigInt::Positive);
22,057✔
233
   g.set_sign(BigInt::Positive);
22,057✔
234

235
   const size_t common2s = std::min(low_zero_bits(f), low_zero_bits(g));
22,057✔
236
   CT::unpoison(common2s);
22,057✔
237

238
   f >>= common2s;
22,057✔
239
   g >>= common2s;
22,057✔
240

241
   f.ct_cond_swap(f.is_even(), g);
44,114✔
242

243
   int32_t delta = 1;
22,057✔
244

245
   const size_t loop_cnt = safegcd_loop_bound(f.bits(), g.bits());
22,057✔
246

247
   BigInt newg, t;
22,057✔
248
   for(size_t i = 0; i != loop_cnt; ++i) {
5,383,862✔
249
      sub_abs(newg, f, g);
5,361,805✔
250

251
      const bool need_swap = (g.is_odd() && delta > 0);
10,723,610✔
252

253
      // if(need_swap) { delta *= -1 } else { delta *= 1 }
254
      delta *= CT::Mask<uint8_t>::expand(need_swap).if_not_set_return(2) - 1;
5,361,805✔
255
      f.ct_cond_swap(need_swap, g);
5,361,805✔
256
      g.ct_cond_swap(need_swap, newg);
5,361,805✔
257

258
      delta += 1;
5,361,805✔
259

260
      g.ct_cond_add(g.is_odd(), f);
10,723,610✔
261
      g >>= 1;
5,361,805✔
262
   }
263

264
   f <<= common2s;
22,057✔
265

266
   f.const_time_unpoison();
22,057✔
267
   g.const_time_unpoison();
22,057✔
268

269
   BOTAN_ASSERT_NOMSG(g.is_zero());
44,114✔
270

271
   return f;
22,057✔
272
}
88,236✔
273

274
/*
275
* Calculate the LCM
276
*/
277
BigInt lcm(const BigInt& a, const BigInt& b) {
490✔
278
   if(a == b) {
490✔
279
      return a;
×
280
   }
281

282
   auto ab = a * b;
490✔
283
   ab.set_sign(BigInt::Positive);  // ignore the signs of a & b
490✔
284
   const auto g = gcd(a, b);
490✔
285
   return ct_divide(ab, g);
490✔
286
}
980✔
287

288
/*
289
* Modular Exponentiation
290
*/
291
BigInt power_mod(const BigInt& base, const BigInt& exp, const BigInt& mod) {
203✔
292
   if(mod.is_negative() || mod == 1) {
406✔
293
      return BigInt::zero();
×
294
   }
295

296
   if(base.is_zero() || mod.is_zero()) {
548✔
297
      if(exp.is_zero()) {
2✔
298
         return BigInt::one();
1✔
299
      }
300
      return BigInt::zero();
×
301
   }
302

303
   Modular_Reducer reduce_mod(mod);
202✔
304

305
   const size_t exp_bits = exp.bits();
202✔
306

307
   if(mod.is_odd()) {
404✔
308
      auto monty_params = std::make_shared<Montgomery_Params>(mod, reduce_mod);
179✔
309
      return monty_exp(monty_params, reduce_mod.reduce(base), exp, exp_bits);
716✔
310
   }
179✔
311

312
   /*
313
   Support for even modulus is just a convenience and not considered
314
   cryptographically important, so this implementation is slow ...
315
   */
316
   BigInt accum = BigInt::one();
23✔
317
   BigInt g = reduce_mod.reduce(base);
23✔
318
   BigInt t;
23✔
319

320
   for(size_t i = 0; i != exp_bits; ++i) {
6,006✔
321
      t = reduce_mod.multiply(g, accum);
5,983✔
322
      g = reduce_mod.square(g);
5,983✔
323
      accum.ct_cond_assign(exp.get_bit(i), t);
11,966✔
324
   }
325
   return accum;
23✔
326
}
248✔
327

328
BigInt is_perfect_square(const BigInt& C) {
706✔
329
   if(C < 1) {
706✔
330
      throw Invalid_Argument("is_perfect_square requires C >= 1");
×
331
   }
332
   if(C == 1) {
706✔
333
      return BigInt::one();
×
334
   }
335

336
   const size_t n = C.bits();
706✔
337
   const size_t m = (n + 1) / 2;
706✔
338
   const BigInt B = C + BigInt::power_of_2(m);
706✔
339

340
   BigInt X = BigInt::power_of_2(m) - 1;
1,412✔
341
   BigInt X2 = (X * X);
706✔
342

343
   for(;;) {
1,678✔
344
      X = (X2 + C) / (2 * X);
5,034✔
345
      X2 = (X * X);
1,678✔
346

347
      if(X2 < B) {
1,678✔
348
         break;
349
      }
350
   }
351

352
   if(X2 == C) {
706✔
353
      return X;
706✔
354
   } else {
355
      return BigInt::zero();
643✔
356
   }
357
}
2,055✔
358

359
/*
360
* Test for primality using Miller-Rabin
361
*/
362
bool is_prime(const BigInt& n, RandomNumberGenerator& rng, size_t prob, bool is_random) {
51,988✔
363
   if(n == 2) {
51,988✔
364
      return true;
365
   }
366
   if(n <= 1 || n.is_even()) {
103,972✔
367
      return false;
368
   }
369

370
   const size_t n_bits = n.bits();
51,984✔
371

372
   // Fast path testing for small numbers (<= 65521)
373
   if(n_bits <= 16) {
51,984✔
374
      const uint16_t num = static_cast<uint16_t>(n.word_at(0));
32,791✔
375

376
      return std::binary_search(PRIMES, PRIMES + PRIME_TABLE_SIZE, num);
32,791✔
377
   }
378

379
   Modular_Reducer mod_n(n);
19,193✔
380

381
   if(rng.is_seeded()) {
19,193✔
382
      const size_t t = miller_rabin_test_iterations(n_bits, prob, is_random);
19,193✔
383

384
      if(is_miller_rabin_probable_prime(n, mod_n, rng, t) == false) {
19,193✔
385
         return false;
386
      }
387

388
      if(is_random) {
3,349✔
389
         return true;
390
      } else {
391
         return is_lucas_probable_prime(n, mod_n);
3,156✔
392
      }
393
   } else {
394
      return is_bailie_psw_probable_prime(n, mod_n);
×
395
   }
396
}
19,193✔
397

398
}  // namespace Botan
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc