Botan 3.10.0
Crypto and TLS for C&
divide.cpp
Go to the documentation of this file.
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/ct_utils.h>
11#include <botan/internal/mp_core.h>
12
13namespace Botan {
14
15namespace {
16
17/*
18* Handle signed operands, if necessary
19*/
20void sign_fixup(const BigInt& x, const BigInt& y, BigInt& q, BigInt& r) {
21 q.cond_flip_sign(x.sign() != y.sign());
22
23 if(x.is_negative() && r.is_nonzero()) {
24 q -= 1;
25 r = y.abs() - r;
26 }
27}
28
29inline bool division_check_vartime(word q, word y2, word y1, word x3, word x2, word x1) {
30 /*
31 Compute (y3,y2,y1) = (y2,y1) * q
32 and return true if (y3,y2,y1) > (x3,x2,x1)
33 */
34
35 word y3 = 0;
36 y1 = word_madd2(q, y1, &y3);
37 y2 = word_madd2(q, y2, &y3);
38
39 if(x3 != y3) {
40 return (y3 > x3);
41 }
42 if(x2 != y2) {
43 return (y2 > x2);
44 }
45 return (y1 > x1);
46}
47
48} // namespace
49
50void ct_divide(const BigInt& x, const BigInt& y, BigInt& q_out, BigInt& r_out) {
51 if(y.is_zero()) {
52 throw Invalid_Argument("ct_divide: cannot divide by zero");
53 }
54
55 const size_t x_words = x.sig_words();
56 const size_t y_words = y.sig_words();
57
58 const size_t x_bits = x.bits();
59
60 BigInt q = BigInt::with_capacity(x_words);
61 BigInt r = BigInt::with_capacity(y_words);
62 BigInt t = BigInt::with_capacity(y_words); // a temporary
63
64 for(size_t i = 0; i != x_bits; ++i) {
65 const size_t b = x_bits - 1 - i;
66 const bool x_b = x.get_bit(b);
67
68 r <<= 1;
69 r.conditionally_set_bit(0, x_b);
70
71 const bool r_gte_y = bigint_sub3(t.mutable_data(), r._data(), r.size(), y._data(), y_words) == 0;
72
73 q.conditionally_set_bit(b, r_gte_y);
74 r.ct_cond_swap(r_gte_y, t);
75 }
76
77 sign_fixup(x, y, q, r);
78 r_out = r;
79 q_out = q;
80}
81
82BigInt ct_divide_pow2k(size_t k, const BigInt& y) {
83 BOTAN_ARG_CHECK(!y.is_zero(), "Cannot divide by zero");
84 BOTAN_ARG_CHECK(!y.is_negative(), "Negative divisor not supported");
85 BOTAN_ARG_CHECK(k > 1, "Invalid k");
86
87 const size_t x_bits = k + 1;
88 const size_t y_bits = y.bits();
89
90 if(x_bits < y_bits) {
91 return BigInt::zero();
92 }
93
94 BOTAN_ASSERT_NOMSG(y_bits >= 1);
95 const size_t x_words = (x_bits + WordInfo<word>::bits - 1) / WordInfo<word>::bits;
96 const size_t y_words = y.sig_words();
97
98 BigInt q = BigInt::with_capacity(x_words);
99 BigInt r = BigInt::with_capacity(y_words + 1);
100 BigInt t = BigInt::with_capacity(y_words + 1); // a temporary
101
102 r.set_bit(y_bits - 1);
103 for(size_t i = y_bits - 1; i != x_bits; ++i) {
104 const size_t b = x_bits - 1 - i;
105
106 if(i >= y_bits) {
107 bigint_shl1(r.mutable_data(), r.size(), r.size(), 1);
108 }
109
110 const bool r_gte_y = bigint_sub3(t.mutable_data(), r._data(), r.size(), y._data(), y_words) == 0;
111
112 q.conditionally_set_bit(b, r_gte_y);
113
114 bigint_cnd_swap(static_cast<word>(r_gte_y), r.mutable_data(), t.mutable_data(), y_words + 1);
115 }
116
117 // No need for sign fixup
118
119 return q;
120}
121
122void ct_divide_word(const BigInt& x, word y, BigInt& q_out, word& r_out) {
123 if(y == 0) {
124 throw Invalid_Argument("ct_divide_word: cannot divide by zero");
125 }
126
127 const size_t x_words = x.sig_words();
128 const size_t x_bits = x.bits();
129
130 BigInt q = BigInt::with_capacity(x_words);
131 word r = 0;
132
133 for(size_t i = 0; i != x_bits; ++i) {
134 const size_t b = x_bits - 1 - i;
135 const bool x_b = x.get_bit(b);
136
137 const auto r_carry = CT::Mask<word>::expand_top_bit(r);
138
139 r <<= 1;
140 r += static_cast<word>(x_b);
141
142 const auto r_gte_y = CT::Mask<word>::is_gte(r, y) | r_carry;
143 q.conditionally_set_bit(b, r_gte_y.as_bool());
144 r = r_gte_y.select(r - y, r);
145 }
146
147 if(x.is_negative()) {
148 q.flip_sign();
149 if(r != 0) {
150 --q;
151 r = y - r;
152 }
153 }
154
155 r_out = r;
156 q_out = q;
157}
158
160 BigInt q;
161 word r = 0;
162 ct_divide_word(x, y, q, r);
163 BOTAN_UNUSED(r);
164 return q;
165}
166
168 BOTAN_ARG_CHECK(x.is_positive(), "The argument x must be positive");
169 BOTAN_ARG_CHECK(y != 0, "Cannot divide by zero");
170
171 const size_t x_bits = x.bits();
172
173 word r = 0;
174
175 for(size_t i = 0; i != x_bits; ++i) {
176 const size_t b = x_bits - 1 - i;
177 const bool x_b = x.get_bit(b);
178
179 const auto r_carry = CT::Mask<word>::expand_top_bit(r);
180
181 r <<= 1;
182 r += static_cast<word>(x_b);
183
184 const auto r_gte_y = CT::Mask<word>::is_gte(r, y) | r_carry;
185 r = r_gte_y.select(r - y, r);
186 }
187
188 return r;
189}
190
191BigInt ct_modulo(const BigInt& x, const BigInt& y) {
192 if(y.is_negative() || y.is_zero()) {
193 throw Invalid_Argument("ct_modulo requires y > 0");
194 }
195
196 const size_t y_words = y.sig_words();
197
198 const size_t x_bits = x.bits();
199
200 BigInt r = BigInt::with_capacity(y_words);
201 BigInt t = BigInt::with_capacity(y_words);
202
203 for(size_t i = 0; i != x_bits; ++i) {
204 const size_t b = x_bits - 1 - i;
205 const bool x_b = x.get_bit(b);
206
207 r <<= 1;
208 r.conditionally_set_bit(0, x_b);
209
210 const bool r_gte_y = bigint_sub3(t.mutable_data(), r._data(), r.size(), y._data(), y_words) == 0;
211
212 r.ct_cond_swap(r_gte_y, t);
213 }
214
215 if(x.is_negative()) {
216 if(r.is_nonzero()) {
217 r = y - r;
218 }
219 }
220
221 return r;
222}
223
224BigInt vartime_divide_pow2k(size_t k, const BigInt& y_arg) {
225 constexpr size_t WB = WordInfo<word>::bits;
226
227 BOTAN_ARG_CHECK(!y_arg.is_zero(), "Cannot divide by zero");
228 BOTAN_ARG_CHECK(!y_arg.is_negative(), "Negative divisor not supported");
229 BOTAN_ARG_CHECK(k > 1, "Invalid k");
230
231 BigInt y = y_arg;
232
233 const size_t y_words = y.sig_words();
234
235 BOTAN_ASSERT_NOMSG(y_words > 0);
236
237 // Calculate shifts needed to normalize y with high bit set
238 const size_t shifts = y.top_bits_free();
239
240 if(shifts > 0) {
241 y <<= shifts;
242 }
243
244 BigInt r;
245 r.set_bit(k + shifts); // (2^k) << shifts
246
247 // we know y has not changed size, since we only shifted up to set high bit
248 const size_t t = y_words - 1;
249 const size_t n = std::max(y_words, r.sig_words()) - 1;
250
251 BOTAN_ASSERT_NOMSG(n >= t);
252
253 BigInt q = BigInt::zero();
254 q.grow_to(n - t + 1);
255
256 word* q_words = q.mutable_data();
257
258 BigInt shifted_y = y << (WB * (n - t));
259
260 // Set q_{n-t} to number of times r > shifted_y
262 q_words[n - t] = r.reduce_below(shifted_y, ws);
263
264 const word y_t0 = y.word_at(t);
265 const word y_t1 = y.word_at(t - 1);
266 BOTAN_DEBUG_ASSERT((y_t0 >> (WB - 1)) == 1);
267
268 divide_precomp div_y_t0(y_t0);
269
270 for(size_t i = n; i != t; --i) {
271 const word x_i0 = r.word_at(i);
272 const word x_i1 = r.word_at(i - 1);
273 const word x_i2 = r.word_at(i - 2);
274
275 word qit = (x_i0 == y_t0) ? WordInfo<word>::max : div_y_t0.vartime_div_2to1(x_i0, x_i1);
276
277 // Per HAC 14.23, this operation is required at most twice
278 for(size_t j = 0; j != 2; ++j) {
279 if(division_check_vartime(qit, y_t0, y_t1, x_i0, x_i1, x_i2)) {
280 BOTAN_ASSERT_NOMSG(qit > 0);
281 qit--;
282 } else {
283 break;
284 }
285 }
286
287 shifted_y >>= WB;
288 // Now shifted_y == y << (WB * (i-t-1))
289
290 /*
291 * Special case qit == 0 and qit == 1 which occurs relatively often here due to a
292 * combination of the fixed 2^k and in many cases the typical structure of
293 * public moduli (as this function is called by Barrett_Reduction::for_public_modulus).
294 *
295 * Over the test suite, about 5% of loop iterations have qit == 1 and 10% have qit == 0
296 */
297
298 if(qit != 0) {
299 if(qit == 1) {
300 r -= shifted_y;
301 } else {
302 r -= qit * shifted_y;
303 }
304
305 if(r.is_negative()) {
306 BOTAN_ASSERT_NOMSG(qit > 0);
307 qit--;
308 r += shifted_y;
310 }
311 }
312
313 q_words[i - t - 1] = qit;
314 }
315
316 return q;
317}
318
319/*
320* Solve x = q * y + r
321*
322* See Handbook of Applied Cryptography algorithm 14.20
323*/
324void vartime_divide(const BigInt& x, const BigInt& y_arg, BigInt& q_out, BigInt& r_out) {
325 constexpr size_t WB = WordInfo<word>::bits;
326
327 if(y_arg.is_zero()) {
328 throw Invalid_Argument("vartime_divide: cannot divide by zero");
329 }
330
331 const size_t y_words = y_arg.sig_words();
332
333 BOTAN_ASSERT_NOMSG(y_words > 0);
334
335 BigInt y = y_arg;
336
337 BigInt r = x;
338 BigInt q = BigInt::zero();
340
343
344 // Calculate shifts needed to normalize y with high bit set
345 const size_t shifts = y.top_bits_free();
346
347 if(shifts > 0) {
348 y <<= shifts;
349 r <<= shifts;
350 }
351
352 // we know y has not changed size, since we only shifted up to set high bit
353 const size_t t = y_words - 1;
354 const size_t n = std::max(y_words, r.sig_words()) - 1; // r may have changed size however
355
356 BOTAN_ASSERT_NOMSG(n >= t);
357
358 q.grow_to(n - t + 1);
359
360 word* q_words = q.mutable_data();
361
362 BigInt shifted_y = y << (WB * (n - t));
363
364 // Set q_{n-t} to number of times r > shifted_y
365 q_words[n - t] = r.reduce_below(shifted_y, ws);
366
367 const word y_t0 = y.word_at(t);
368 const word y_t1 = y.word_at(t - 1);
369 BOTAN_DEBUG_ASSERT((y_t0 >> (WB - 1)) == 1);
370
371 divide_precomp div_y_t0(y_t0);
372
373 for(size_t i = n; i != t; --i) {
374 const word x_i0 = r.word_at(i);
375 const word x_i1 = r.word_at(i - 1);
376 const word x_i2 = r.word_at(i - 2);
377
378 word qit = (x_i0 == y_t0) ? WordInfo<word>::max : div_y_t0.vartime_div_2to1(x_i0, x_i1);
379
380 // Per HAC 14.23, this operation is required at most twice
381 for(size_t j = 0; j != 2; ++j) {
382 if(division_check_vartime(qit, y_t0, y_t1, x_i0, x_i1, x_i2)) {
383 BOTAN_ASSERT_NOMSG(qit > 0);
384 qit--;
385 } else {
386 break;
387 }
388 }
389
390 shifted_y >>= WB;
391 // Now shifted_y == y << (WB * (i-t-1))
392
393 if(qit != 0) {
394 r -= qit * shifted_y;
395 if(r.is_negative()) {
396 BOTAN_ASSERT_NOMSG(qit > 0);
397 qit--;
398 r += shifted_y;
400 }
401 }
402
403 q_words[i - t - 1] = qit;
404 }
405
406 if(shifts > 0) {
407 r >>= shifts;
408 }
409
410 sign_fixup(x, y_arg, q, r);
411
412 r_out = r;
413 q_out = q;
414}
415
416} // namespace Botan
#define BOTAN_UNUSED
Definition assert.h:144
#define BOTAN_ASSERT_NOMSG(expr)
Definition assert.h:75
#define BOTAN_DEBUG_ASSERT(expr)
Definition assert.h:129
#define BOTAN_ARG_CHECK(expr, msg)
Definition assert.h:33
static BigInt zero()
Definition bigint.h:49
size_t sig_words() const
Definition bigint.h:615
void conditionally_set_bit(size_t n, bool set_it)
Definition bigint.h:473
word * mutable_data()
Definition bigint.h:640
size_t size() const
Definition bigint.h:609
void grow_to(size_t n) const
Definition bigint.h:666
void flip_sign()
Definition bigint.h:586
size_t top_bits_free() const
Definition bigint.cpp:302
word word_at(size_t n) const
Definition bigint.h:547
void set_bit(size_t n)
Definition bigint.h:463
size_t bits() const
Definition bigint.cpp:311
const word * _data() const
Definition bigint.h:936
void ct_cond_swap(bool predicate, BigInt &other)
Definition bigint.cpp:511
bool is_zero() const
Definition bigint.h:457
size_t reduce_below(const BigInt &mod, secure_vector< word > &ws)
Definition bigint.cpp:333
bool is_negative() const
Definition bigint.h:559
bool is_nonzero() const
Definition bigint.h:451
bool is_positive() const
Definition bigint.h:565
bool get_bit(size_t n) const
Definition bigint.h:496
static BigInt with_capacity(size_t n)
Definition bigint.cpp:50
void set_sign(Sign sign)
Definition bigint.h:592
static constexpr Mask< T > is_gte(T x, T y)
Definition ct_utils.h:496
static constexpr Mask< T > expand_top_bit(T v)
Definition ct_utils.h:443
constexpr W vartime_div_2to1(W n1, W n0) const
Definition mp_core.h:548
constexpr void bigint_cnd_swap(W cnd, W x[], W y[], size_t size)
Definition mp_core.h:31
void vartime_divide(const BigInt &x, const BigInt &y_arg, BigInt &q_out, BigInt &r_out)
Definition divide.cpp:324
word ct_mod_word(const BigInt &x, word y)
Definition divide.cpp:167
constexpr auto word_madd2(W a, W b, W *c) -> W
Definition mp_asmi.h:86
constexpr auto bigint_sub3(W z[], const W x[], size_t x_size, const W y[], size_t y_size) -> W
Definition mp_core.h:194
constexpr void bigint_shl1(W x[], size_t x_size, size_t x_words, size_t shift)
Definition mp_core.h:309
BigInt ct_modulo(const BigInt &x, const BigInt &y)
Definition divide.cpp:191
BigInt vartime_divide_pow2k(size_t k, const BigInt &y_arg)
Definition divide.cpp:224
void ct_divide(const BigInt &x, const BigInt &y, BigInt &q_out, BigInt &r_out)
Definition divide.cpp:50
void ct_divide_word(const BigInt &x, word y, BigInt &q_out, word &r_out)
Definition divide.cpp:122
BigInt ct_divide_pow2k(size_t k, const BigInt &y)
Definition divide.cpp:82
std::vector< T, secure_allocator< T > > secure_vector
Definition secmem.h:69
std::conditional_t< HasNative64BitRegisters, std::uint64_t, uint32_t > word
Definition types.h:119