Coverage Report

Created: 2026-09-28 06:36

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/botan/src/lib/math/bigint/divide.cpp
Line
Count
Source
1
/*
2
* Division Algorithms
3
* (C) 1999-2007,2012,2018,2021 Jack Lloyd
4
*
5
* Botan is released under the Simplified BSD License (see license.txt)
6
*/
7
8
#include <botan/internal/divide.h>
9
10
#include <botan/internal/bit_ops.h>
11
#include <botan/internal/ct_utils.h>
12
#include <botan/internal/mp_core.h>
13
14
namespace Botan {
15
16
namespace {
17
18
/*
19
* Handle signed operands, if necessary
20
*/
21
12.3k
void sign_fixup(const BigInt& x, const BigInt& y, BigInt& q, BigInt& r) {
22
12.3k
   q.cond_flip_sign(x.sign() != y.sign());
23
24
12.3k
   if(x.is_negative() && r.is_nonzero()) {
25
127
      q -= 1;
26
127
      r = y.abs() - r;
27
127
   }
28
12.3k
}
29
30
46.7k
inline bool division_check_vartime(word q, word y2, word y1, word x3, word x2, word x1) {
31
   /*
32
   Compute (y3,y2,y1) = (y2,y1) * q
33
   and return true if (y3,y2,y1) > (x3,x2,x1)
34
   */
35
36
46.7k
   word y3 = 0;
37
46.7k
   y1 = word_madd2(q, y1, &y3);
38
46.7k
   y2 = word_madd2(q, y2, &y3);
39
40
46.7k
   if(x3 != y3) {
41
17.1k
      return (y3 > x3);
42
17.1k
   }
43
29.5k
   if(x2 != y2) {
44
28.9k
      return (y2 > x2);
45
28.9k
   }
46
599
   return (y1 > x1);
47
29.5k
}
48
49
}  // namespace
50
51
0
void ct_divide(const BigInt& x, const BigInt& y, BigInt& q_out, BigInt& r_out) {
52
0
   if(y.is_zero()) {
53
0
      throw Invalid_Argument("ct_divide: cannot divide by zero");
54
0
   }
55
56
0
   const size_t x_words = x.sig_words();
57
0
   const size_t y_words = y.sig_words();
58
59
0
   const size_t x_bits = x.bits();
60
61
0
   BigInt q = BigInt::with_capacity(x_words);
62
0
   BigInt r = BigInt::with_capacity(y_words);
63
0
   BigInt t = BigInt::with_capacity(y_words);  // a temporary
64
65
0
   for(size_t i = 0; i != x_bits; ++i) {
66
0
      const size_t b = x_bits - 1 - i;
67
0
      const bool x_b = x.get_bit(b);
68
69
0
      r <<= 1;
70
0
      r.conditionally_set_bit(0, x_b);
71
72
0
      const bool r_gte_y = bigint_sub3(t.mutable_data(), r._data(), r.size(), y._data(), y_words) == 0;
73
74
0
      q.conditionally_set_bit(b, r_gte_y);
75
0
      r.ct_cond_swap(r_gte_y, t);
76
0
   }
77
78
0
   sign_fixup(x, y, q, r);
79
0
   r_out = r;
80
0
   q_out = q;
81
0
}
82
83
43
BigInt ct_divide_pow2k(size_t k, const BigInt& y) {
84
43
   BOTAN_ARG_CHECK(!y.is_zero(), "Cannot divide by zero");
85
43
   BOTAN_ARG_CHECK(!y.is_negative(), "Negative divisor not supported");
86
43
   BOTAN_ARG_CHECK(k > 1, "Invalid k");
87
88
43
   const size_t x_bits = k + 1;
89
43
   const size_t y_bits = y.bits();
90
91
43
   if(x_bits < y_bits) {
92
0
      return BigInt::zero();
93
0
   }
94
95
43
   BOTAN_ASSERT_NOMSG(y_bits >= 1);
96
43
   const size_t x_words = (x_bits + WordInfo<word>::bits - 1) / WordInfo<word>::bits;
97
43
   const size_t y_words = y.sig_words();
98
99
43
   BigInt q = BigInt::with_capacity(x_words);
100
43
   BigInt r = BigInt::with_capacity(y_words + 1);
101
43
   BigInt t = BigInt::with_capacity(y_words + 1);  // a temporary
102
103
43
   r.set_bit(y_bits - 1);
104
13.7k
   for(size_t i = y_bits - 1; i != x_bits; ++i) {
105
13.7k
      const size_t b = x_bits - 1 - i;
106
107
13.7k
      if(i >= y_bits) {
108
13.6k
         bigint_shl1(r.mutable_data(), r.size(), r.size(), 1);
109
13.6k
      }
110
111
13.7k
      const bool r_gte_y = bigint_sub3(t.mutable_data(), r._data(), r.size(), y._data(), y_words) == 0;
112
113
13.7k
      q.conditionally_set_bit(b, r_gte_y);
114
115
13.7k
      bigint_cnd_swap(static_cast<word>(r_gte_y), r.mutable_data(), t.mutable_data(), y_words + 1);
116
13.7k
   }
117
118
   // No need for sign fixup
119
120
43
   return q;
121
43
}
122
123
25.5k
void ct_divide_word(const BigInt& x, word y, BigInt& q_out, word& r_out) {
124
25.5k
   if(y == 0) {
125
0
      throw Invalid_Argument("ct_divide_word: cannot divide by zero");
126
0
   }
127
128
25.5k
   const size_t x_words = x.sig_words();
129
25.5k
   const size_t x_bits = x.bits();
130
131
25.5k
   BigInt q = BigInt::with_capacity(x_words);
132
25.5k
   word r = 0;
133
134
3.25M
   for(size_t i = 0; i != x_bits; ++i) {
135
3.22M
      const size_t b = x_bits - 1 - i;
136
3.22M
      const bool x_b = x.get_bit(b);
137
138
3.22M
      const auto r_carry = CT::Mask<word>::expand_top_bit(r);
139
140
3.22M
      r <<= 1;
141
3.22M
      r += static_cast<word>(x_b);
142
143
3.22M
      const auto r_gte_y = CT::Mask<word>::is_gte(r, y) | r_carry;
144
3.22M
      q.conditionally_set_bit(b, r_gte_y.as_bool());
145
3.22M
      r = r_gte_y.select(r - y, r);
146
3.22M
   }
147
148
25.5k
   if(x.is_negative()) {
149
0
      q.flip_sign();
150
0
      if(r != 0) {
151
0
         --q;
152
0
         r = y - r;
153
0
      }
154
0
   }
155
156
25.5k
   r_out = r;
157
25.5k
   q_out = q;
158
25.5k
}
159
160
0
BigInt ct_divide_word(const BigInt& x, word y) {
161
0
   BigInt q;
162
0
   word r = 0;
163
0
   ct_divide_word(x, y, q, r);
164
0
   BOTAN_UNUSED(r);
165
0
   return q;
166
0
}
167
168
0
word ct_mod_word(const BigInt& x, word y) {
169
0
   BOTAN_ARG_CHECK(x.is_positive(), "The argument x must be positive");
170
0
   BOTAN_ARG_CHECK(y != 0, "Cannot divide by zero");
171
172
0
   const size_t x_bits = x.bits();
173
174
0
   word r = 0;
175
176
0
   for(size_t i = 0; i != x_bits; ++i) {
177
0
      const size_t b = x_bits - 1 - i;
178
0
      const bool x_b = x.get_bit(b);
179
180
0
      const auto r_carry = CT::Mask<word>::expand_top_bit(r);
181
182
0
      r <<= 1;
183
0
      r += static_cast<word>(x_b);
184
185
0
      const auto r_gte_y = CT::Mask<word>::is_gte(r, y) | r_carry;
186
0
      r = r_gte_y.select(r - y, r);
187
0
   }
188
189
0
   return r;
190
0
}
191
192
53
BigInt ct_modulo(const BigInt& x, const BigInt& y) {
193
53
   if(y.is_negative() || y.is_zero()) {
194
0
      throw Invalid_Argument("ct_modulo requires y > 0");
195
0
   }
196
197
53
   const size_t y_words = y.sig_words();
198
199
53
   const size_t x_bits = x.bits();
200
201
53
   BigInt r = BigInt::with_capacity(y_words);
202
53
   BigInt t = BigInt::with_capacity(y_words);
203
204
22.2k
   for(size_t i = 0; i != x_bits; ++i) {
205
22.2k
      const size_t b = x_bits - 1 - i;
206
22.2k
      const bool x_b = x.get_bit(b);
207
208
22.2k
      r <<= 1;
209
22.2k
      r.conditionally_set_bit(0, x_b);
210
211
22.2k
      const bool r_gte_y = bigint_sub3(t.mutable_data(), r._data(), r.size(), y._data(), y_words) == 0;
212
213
22.2k
      r.ct_cond_swap(r_gte_y, t);
214
22.2k
   }
215
216
53
   if(x.is_negative()) {
217
0
      if(r.is_nonzero()) {
218
0
         r = y - r;
219
0
      }
220
0
   }
221
222
53
   return r;
223
53
}
224
225
/*
226
* Solve x = q * y + r
227
*
228
* See Handbook of Applied Cryptography section 14.2.5
229
*/
230
12.3k
void vartime_divide(const BigInt& x, const BigInt& y_arg, BigInt& q_out, BigInt& r_out) {
231
12.3k
   if(y_arg.is_zero()) {
232
0
      throw Invalid_Argument("vartime_divide: cannot divide by zero");
233
0
   }
234
235
12.3k
   const size_t y_words = y_arg.sig_words();
236
237
12.3k
   BOTAN_ASSERT_NOMSG(y_words > 0);
238
239
12.3k
   BigInt y = y_arg;
240
241
12.3k
   BigInt r = x;
242
12.3k
   BigInt q = BigInt::zero();
243
12.3k
   secure_vector<word> ws;
244
245
12.3k
   r.set_sign(BigInt::Positive);
246
12.3k
   y.set_sign(BigInt::Positive);
247
248
   // Calculate shifts needed to normalize y with high bit set
249
12.3k
   const size_t shifts = y.top_bits_free();
250
251
12.3k
   if(shifts > 0) {
252
12.1k
      y <<= shifts;
253
12.1k
      r <<= shifts;
254
12.1k
   }
255
256
   // we know y has not changed size, since we only shifted up to set high bit
257
12.3k
   const size_t t = y_words - 1;
258
12.3k
   const size_t n = std::max(y_words, r.sig_words()) - 1;  // r may have changed size however
259
260
12.3k
   BOTAN_ASSERT_NOMSG(n >= t);
261
262
12.3k
   q.grow_to(n - t + 1);
263
264
12.3k
   word* q_words = q.mutable_data();
265
266
12.3k
   BigInt shifted_y = y << (WordInfo<word>::bits * (n - t));
267
268
   // Set q_{n-t} to number of times r > shifted_y
269
12.3k
   q_words[n - t] = r.reduce_below(shifted_y, ws);
270
271
12.3k
   const word y_t0 = y.word_at(t);
272
12.3k
   const word y_t1 = y.word_at(t - 1);
273
12.3k
   BOTAN_DEBUG_ASSERT((y_t0 >> (WordInfo<word>::bits - 1)) == 1);
274
275
52.9k
   for(size_t j = n; j != t; --j) {
276
40.6k
      const word x_j0 = r.word_at(j);
277
40.6k
      const word x_j1 = r.word_at(j - 1);
278
40.6k
      const word x_j2 = r.word_at(j - 2);
279
280
40.6k
      word qjt = (x_j0 == y_t0) ? WordInfo<word>::max : bigint_divop_vartime(x_j0, x_j1, y_t0);
281
282
      // Per HAC 14.23, this operation is required at most twice
283
46.7k
      for(size_t k = 0; k != 2; ++k) {
284
46.7k
         if(division_check_vartime(qjt, y_t0, y_t1, x_j0, x_j1, x_j2)) {
285
6.06k
            qjt--;
286
40.6k
         } else {
287
40.6k
            break;
288
40.6k
         }
289
46.7k
      }
290
291
40.6k
      shifted_y >>= WordInfo<word>::bits;
292
      // Now shifted_y == y << (WordInfo<word>::bits * (j-t-1))
293
294
      // TODO this sequence could be better
295
40.6k
      r -= qjt * shifted_y;
296
40.6k
      if(r.is_negative()) {
297
26
         qjt--;
298
26
         r += shifted_y;
299
26
         BOTAN_ASSERT_NOMSG(r.is_positive());
300
26
      }
301
302
40.6k
      q_words[j - t - 1] = qjt;
303
40.6k
   }
304
305
12.3k
   if(shifts > 0) {
306
12.1k
      r >>= shifts;
307
12.1k
   }
308
309
12.3k
   sign_fixup(x, y_arg, q, r);
310
311
12.3k
   r_out = r;
312
12.3k
   q_out = q;
313
12.3k
}
314
315
}  // namespace Botan