Coverage Report

Created: 2026-07-25 06:49

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
59.7k
void sign_fixup(const BigInt& x, const BigInt& y, BigInt& q, BigInt& r) {
22
59.7k
   q.cond_flip_sign(x.sign() != y.sign());
23
24
59.7k
   if(x.is_negative() && r.is_nonzero()) {
25
0
      q -= 1;
26
0
      r = y.abs() - r;
27
0
   }
28
59.7k
}
29
30
84.0k
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
84.0k
   word y3 = 0;
37
84.0k
   y1 = word_madd2(q, y1, &y3);
38
84.0k
   y2 = word_madd2(q, y2, &y3);
39
40
84.0k
   if(x3 != y3) {
41
29.5k
      return (y3 > x3);
42
29.5k
   }
43
54.4k
   if(x2 != y2) {
44
54.1k
      return (y2 > x2);
45
54.1k
   }
46
361
   return (y1 > x1);
47
54.4k
}
48
49
}  // namespace
50
51
241
void ct_divide(const BigInt& x, const BigInt& y, BigInt& q_out, BigInt& r_out) {
52
241
   if(y.is_zero()) {
53
0
      throw Invalid_Argument("ct_divide: cannot divide by zero");
54
0
   }
55
56
241
   const size_t x_words = x.sig_words();
57
241
   const size_t y_words = y.sig_words();
58
59
241
   const size_t x_bits = x.bits();
60
61
241
   BigInt q = BigInt::with_capacity(x_words);
62
241
   BigInt r = BigInt::with_capacity(y_words);
63
241
   BigInt t = BigInt::with_capacity(y_words);  // a temporary
64
65
477k
   for(size_t i = 0; i != x_bits; ++i) {
66
477k
      const size_t b = x_bits - 1 - i;
67
477k
      const bool x_b = x.get_bit(b);
68
69
477k
      r <<= 1;
70
477k
      r.conditionally_set_bit(0, x_b);
71
72
477k
      const bool r_gte_y = bigint_sub3(t.mutable_data(), r._data(), r.size(), y._data(), y_words) == 0;
73
74
477k
      q.conditionally_set_bit(b, r_gte_y);
75
477k
      r.ct_cond_swap(r_gte_y, t);
76
477k
   }
77
78
241
   sign_fixup(x, y, q, r);
79
241
   r_out = r;
80
241
   q_out = q;
81
241
}
82
83
871
BigInt ct_divide_pow2k(size_t k, const BigInt& y) {
84
871
   BOTAN_ARG_CHECK(!y.is_zero(), "Cannot divide by zero");
85
871
   BOTAN_ARG_CHECK(!y.is_negative(), "Negative divisor not supported");
86
871
   BOTAN_ARG_CHECK(k > 1, "Invalid k");
87
88
871
   const size_t x_bits = k + 1;
89
871
   const size_t y_bits = y.bits();
90
91
871
   if(x_bits < y_bits) {
92
0
      return BigInt::zero();
93
0
   }
94
95
871
   BOTAN_ASSERT_NOMSG(y_bits >= 1);
96
871
   const size_t x_words = (x_bits + WordInfo<word>::bits - 1) / WordInfo<word>::bits;
97
871
   const size_t y_words = y.sig_words();
98
99
871
   BigInt q = BigInt::with_capacity(x_words);
100
871
   BigInt r = BigInt::with_capacity(y_words + 1);
101
871
   BigInt t = BigInt::with_capacity(y_words + 1);  // a temporary
102
103
871
   r.set_bit(y_bits - 1);
104
618k
   for(size_t i = y_bits - 1; i != x_bits; ++i) {
105
617k
      const size_t b = x_bits - 1 - i;
106
107
617k
      if(i >= y_bits) {
108
616k
         bigint_shl1(r.mutable_data(), r.size(), r.size(), 1);
109
616k
      }
110
111
617k
      const bool r_gte_y = bigint_sub3(t.mutable_data(), r._data(), r.size(), y._data(), y_words) == 0;
112
113
617k
      q.conditionally_set_bit(b, r_gte_y);
114
115
617k
      bigint_cnd_swap(static_cast<word>(r_gte_y), r.mutable_data(), t.mutable_data(), y_words + 1);
116
617k
   }
117
118
   // No need for sign fixup
119
120
871
   return q;
121
871
}
122
123
81.4k
void ct_divide_word(const BigInt& x, word y, BigInt& q_out, word& r_out) {
124
81.4k
   if(y == 0) {
125
0
      throw Invalid_Argument("ct_divide_word: cannot divide by zero");
126
0
   }
127
128
81.4k
   const size_t x_words = x.sig_words();
129
81.4k
   const size_t x_bits = x.bits();
130
131
81.4k
   BigInt q = BigInt::with_capacity(x_words);
132
81.4k
   word r = 0;
133
134
128M
   for(size_t i = 0; i != x_bits; ++i) {
135
128M
      const size_t b = x_bits - 1 - i;
136
128M
      const bool x_b = x.get_bit(b);
137
138
128M
      const auto r_carry = CT::Mask<word>::expand_top_bit(r);
139
140
128M
      r <<= 1;
141
128M
      r += x_b;
142
143
128M
      const auto r_gte_y = CT::Mask<word>::is_gte(r, y) | r_carry;
144
128M
      q.conditionally_set_bit(b, r_gte_y.as_bool());
145
128M
      r = r_gte_y.select(r - y, r);
146
128M
   }
147
148
81.4k
   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
81.4k
   r_out = r;
157
81.4k
   q_out = q;
158
81.4k
}
159
160
0
BigInt ct_divide_word(const BigInt& x, word y) {
161
0
   BigInt q;
162
0
   word r;
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 += 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
1.23k
BigInt ct_modulo(const BigInt& x, const BigInt& y) {
193
1.23k
   if(y.is_negative() || y.is_zero()) {
194
18
      throw Invalid_Argument("ct_modulo requires y > 0");
195
18
   }
196
197
1.21k
   const size_t y_words = y.sig_words();
198
199
1.21k
   const size_t x_bits = x.bits();
200
201
1.21k
   BigInt r = BigInt::with_capacity(y_words);
202
1.21k
   BigInt t = BigInt::with_capacity(y_words);
203
204
217k
   for(size_t i = 0; i != x_bits; ++i) {
205
215k
      const size_t b = x_bits - 1 - i;
206
215k
      const bool x_b = x.get_bit(b);
207
208
215k
      r <<= 1;
209
215k
      r.conditionally_set_bit(0, x_b);
210
211
215k
      const bool r_gte_y = bigint_sub3(t.mutable_data(), r._data(), r.size(), y._data(), y_words) == 0;
212
213
215k
      r.ct_cond_swap(r_gte_y, t);
214
215k
   }
215
216
1.21k
   if(x.is_negative()) {
217
0
      if(r.is_nonzero()) {
218
0
         r = y - r;
219
0
      }
220
0
   }
221
222
1.21k
   return r;
223
1.23k
}
224
225
/*
226
* Solve x = q * y + r
227
*
228
* See Handbook of Applied Cryptography section 14.2.5
229
*/
230
59.4k
void vartime_divide(const BigInt& x, const BigInt& y_arg, BigInt& q_out, BigInt& r_out) {
231
59.4k
   if(y_arg.is_zero()) {
232
0
      throw Invalid_Argument("vartime_divide: cannot divide by zero");
233
0
   }
234
235
59.4k
   const size_t y_words = y_arg.sig_words();
236
237
59.4k
   BOTAN_ASSERT_NOMSG(y_words > 0);
238
239
59.4k
   BigInt y = y_arg;
240
241
59.4k
   BigInt r = x;
242
59.4k
   BigInt q = BigInt::zero();
243
59.4k
   secure_vector<word> ws;
244
245
59.4k
   r.set_sign(BigInt::Positive);
246
59.4k
   y.set_sign(BigInt::Positive);
247
248
   // Calculate shifts needed to normalize y with high bit set
249
59.4k
   const size_t shifts = y.top_bits_free();
250
251
59.4k
   if(shifts > 0) {
252
58.5k
      y <<= shifts;
253
58.5k
      r <<= shifts;
254
58.5k
   }
255
256
   // we know y has not changed size, since we only shifted up to set high bit
257
59.4k
   const size_t t = y_words - 1;
258
59.4k
   const size_t n = std::max(y_words, r.sig_words()) - 1;  // r may have changed size however
259
260
59.4k
   BOTAN_ASSERT_NOMSG(n >= t);
261
262
59.4k
   q.grow_to(n - t + 1);
263
264
59.4k
   word* q_words = q.mutable_data();
265
266
59.4k
   BigInt shifted_y = y << (WordInfo<word>::bits * (n - t));
267
268
   // Set q_{n-t} to number of times r > shifted_y
269
59.4k
   q_words[n - t] = r.reduce_below(shifted_y, ws);
270
271
59.4k
   const word y_t0 = y.word_at(t);
272
59.4k
   const word y_t1 = y.word_at(t - 1);
273
59.4k
   BOTAN_DEBUG_ASSERT((y_t0 >> (WordInfo<word>::bits - 1)) == 1);
274
275
136k
   for(size_t j = n; j != t; --j) {
276
77.3k
      const word x_j0 = r.word_at(j);
277
77.3k
      const word x_j1 = r.word_at(j - 1);
278
77.3k
      const word x_j2 = r.word_at(j - 2);
279
280
77.3k
      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
84.2k
      for(size_t k = 0; k != 2; ++k) {
284
84.0k
         if(division_check_vartime(qjt, y_t0, y_t1, x_j0, x_j1, x_j2)) {
285
6.87k
            qjt--;
286
77.1k
         } else {
287
77.1k
            break;
288
77.1k
         }
289
84.0k
      }
290
291
77.3k
      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
77.3k
      r -= qjt * shifted_y;
296
77.3k
      if(r.is_negative()) {
297
138
         qjt--;
298
138
         r += shifted_y;
299
138
         BOTAN_DEBUG_ASSERT(r.is_positive());
300
138
      }
301
302
77.3k
      q_words[j - t - 1] = qjt;
303
77.3k
   }
304
305
59.4k
   if(shifts > 0) {
306
58.5k
      r >>= shifts;
307
58.5k
   }
308
309
59.4k
   sign_fixup(x, y_arg, q, r);
310
311
59.4k
   r_out = r;
312
59.4k
   q_out = q;
313
59.4k
}
314
315
}  // namespace Botan