Botan 3.13.0
Crypto and TLS for C&
big_ops2.cpp
Go to the documentation of this file.
1/*
2* (C) 1999-2007,2018 Jack Lloyd
3* 2016 Matthias Gierlings
4*
5* Botan is released under the Simplified BSD License (see license.txt)
6*/
7
8#include <botan/bigint.h>
9
10#include <botan/exceptn.h>
11#include <botan/internal/bit_ops.h>
12#include <botan/internal/mp_core.h>
13
14namespace Botan {
15
17 if(&y == this) {
18 return *this <<= 1;
19 }
20 return add(y._data(), y.sig_words(), y.sign());
21}
22
24 if(&y == this) {
25 this->clear();
26 this->set_sign(Positive);
27 return *this;
28 }
29 return sub(y._data(), y.sig_words(), y.sign());
30}
31
32BigInt& BigInt::add(const word y[], size_t y_words, Sign y_sign) {
33 const size_t x_sw = sig_words();
34
35 grow_to(std::max(x_sw, y_words) + 1);
36
37 if(sign() == y_sign) {
38 const word carry = bigint_add2(mutable_data(), size() - 1, y, y_words);
39 mutable_data()[size() - 1] += carry;
40 } else {
41 const int32_t relative_size = bigint_cmp(_data(), x_sw, y, y_words);
42
43 if(relative_size >= 0) {
44 // *this >= y
45 bigint_sub2(mutable_data(), x_sw, y, y_words);
46 } else {
47 // *this < y: compute *this = y - *this
48 bigint_sub2_rev(mutable_data(), y, y_words);
49 }
50
51 if(relative_size < 0) {
52 set_sign(y_sign);
53 } else if(relative_size == 0) {
55 }
56 }
57
58 return (*this);
59}
60
62 if(this->signum() < 0 || s.signum() < 0 || mod.signum() < 0) {
63 throw Invalid_Argument("BigInt::mod_add expects all arguments are positive");
64 }
65
66 BOTAN_DEBUG_ASSERT(*this < mod);
67 BOTAN_DEBUG_ASSERT(s < mod);
68
69 /*
70 t + s or t + s - p == t - (p - s)
71
72 So first compute ws = p - s
73
74 Then compute t + s and t - ws
75
76 If t - ws does not borrow, then that is the correct valued
77 */
78
79 const size_t mod_sw = mod.sig_words();
80 BOTAN_ARG_CHECK(mod_sw > 0, "BigInt::mod_add modulus must be positive");
81
82 this->grow_to(mod_sw);
83 s.grow_to(mod_sw);
84
85 // First mod_sw for p - s, 2*mod_sw for bigint_addsub workspace
86 if(ws.size() < 3 * mod_sw) {
87 ws.resize(3 * mod_sw);
88 }
89
90 // NOLINTBEGIN(readability-container-data-pointer)
91
92 word borrow = bigint_sub3(&ws[0], mod._data(), mod_sw, s._data(), mod_sw);
93 BOTAN_DEBUG_ASSERT(borrow == 0);
94 BOTAN_UNUSED(borrow);
95
96 // Compute t - ws
97 borrow = bigint_sub3(&ws[mod_sw], this->_data(), mod_sw, &ws[0], mod_sw);
98
99 // Compute t + s
100 bigint_add3(&ws[mod_sw * 2], this->_data(), mod_sw, s._data(), mod_sw);
101
102 CT::conditional_copy_mem(borrow, &ws[0], &ws[mod_sw * 2], &ws[mod_sw], mod_sw);
103 set_words(&ws[0], mod_sw);
104
105 // NOLINTEND(readability-container-data-pointer)
106
107 return (*this);
108}
109
111 if(this->signum() < 0 || s.signum() < 0 || mod.signum() < 0) {
112 throw Invalid_Argument("BigInt::mod_sub expects all arguments are positive");
113 }
114
115 // We are assuming in this function that *this and s are no more than mod_sw words long
116 BOTAN_DEBUG_ASSERT(*this < mod);
117 BOTAN_DEBUG_ASSERT(s < mod);
118
119 const size_t mod_sw = mod.sig_words();
120
121 this->grow_to(mod_sw);
122 s.grow_to(mod_sw);
123
124 if(ws.size() < mod_sw) {
125 ws.resize(mod_sw);
126 }
127
128 const word borrow = bigint_sub3(ws.data(), mutable_data(), mod_sw, s._data(), mod_sw);
129
130 // Conditionally add back the modulus
131 bigint_cnd_add(borrow, ws.data(), mod._data(), mod_sw);
132
133 unchecked_copy_memory(mutable_data(), ws.data(), mod_sw);
134
135 return (*this);
136}
137
138BigInt& BigInt::mod_mul(uint8_t y, const BigInt& mod, secure_vector<word>& ws) {
139 BOTAN_ARG_CHECK(this->signum() >= 0, "*this must be positive");
140 BOTAN_ARG_CHECK(y < 16, "y too large");
141
142 BOTAN_DEBUG_ASSERT(*this < mod);
143
144 *this *= static_cast<word>(y);
145 this->reduce_below(mod, ws);
146 return (*this);
147}
148
149BigInt& BigInt::rev_sub(const word y[], size_t y_sw, secure_vector<word>& ws) {
150 BOTAN_UNUSED(ws);
151 BigInt y_bn;
152 y_bn.m_data.set_words(y, y_sw);
153 *this = y_bn - *this;
154 return (*this);
155}
156
157/*
158* Multiplication Operator
159*/
162 return this->mul(y, ws);
163}
164
166 const size_t x_sw = sig_words();
167 const size_t y_sw = y.sig_words();
168 set_sign((sign() == y.sign()) ? Positive : Negative);
169
170 if(x_sw == 0 || y_sw == 0) {
171 clear();
173 } else if(x_sw == 1 && y_sw > 0) {
174 grow_to(y_sw + 1);
175 bigint_linmul3(mutable_data(), y._data(), y_sw, word_at(0));
176 } else {
177 const size_t new_size = x_sw + y_sw + 1;
178 if(ws.size() < new_size) {
179 ws.resize(new_size);
180 }
181 secure_vector<word> z_reg(new_size);
182
183 bigint_mul(z_reg.data(), z_reg.size(), _data(), size(), x_sw, y._data(), y.size(), y_sw, ws.data(), ws.size());
184
185 this->swap_reg(z_reg);
186 }
187
188 return (*this);
189}
190
192 const size_t sw = sig_words();
193
194 secure_vector<word> z(2 * sw);
195 ws.resize(z.size());
196
197 bigint_sqr(z.data(), z.size(), _data(), size(), sw, ws.data(), ws.size());
198
199 swap_reg(z);
201
202 return (*this);
203}
204
206 if(y == 0) {
207 clear();
209 }
210
211 const word carry = bigint_linmul2(mutable_data(), size(), y);
213
214 return (*this);
215}
216
217/*
218* Division Operator
219*/
221 if(y.sig_words() == 1 && signum() >= 0 && y.signum() >= 0 && is_power_of_2(y.word_at(0))) {
222 (*this) >>= (y.bits() - 1);
223 } else {
224 (*this) = (*this) / y;
225 }
226 return (*this);
227}
228
229/*
230* Modulo Operator
231*/
233 return (*this = (*this) % mod);
234}
235
236/*
237* Modulo Operator
238*/
240 if(mod == 0) {
241 throw Invalid_Argument("BigInt::operator%= divide by zero");
242 }
243
244 word remainder = 0;
245
246 if(is_power_of_2(mod)) {
247 remainder = (word_at(0) & (mod - 1));
248 } else {
249 const divide_precomp redc_mod(mod);
250 const size_t sw = sig_words();
251 for(size_t i = sw; i > 0; --i) {
252 remainder = redc_mod.vartime_mod_2to1(remainder, word_at(i - 1));
253 }
254 }
255
256 if(remainder != 0 && sign() == BigInt::Negative) {
257 remainder = mod - remainder;
258 }
259
260 m_data.set_to_zero();
261 m_data.set_word_at(0, remainder);
263 return remainder;
264}
265
266/*
267* Left Shift Operator
268*/
270 if(shift >= 65536) {
271 throw Invalid_Argument("BigInt left shift count too large");
272 }
273
274 const size_t sw = sig_words();
275 const size_t new_size = sw + (shift + WordInfo<word>::bits - 1) / WordInfo<word>::bits;
276
277 m_data.grow_to(new_size);
278
279 bigint_shl1(m_data.mutable_data(), new_size, sw, shift);
280
281 return (*this);
282}
283
284/*
285* Right Shift Operator
286*/
288 bigint_shr1(m_data.mutable_data(), m_data.size(), shift);
289
290 if(sig_words() == 0 && m_signedness == Negative) {
291 m_signedness = Positive;
292 }
293
294 return (*this);
295}
296
297} // namespace Botan
#define BOTAN_UNUSED
Definition assert.h:144
#define BOTAN_DEBUG_ASSERT(expr)
Definition assert.h:129
#define BOTAN_ARG_CHECK(expr, msg)
Definition assert.h:33
BigInt & operator>>=(size_t shift)
Definition big_ops2.cpp:287
BigInt & mod_mul(uint8_t y, const BigInt &mod, secure_vector< word > &ws)
Definition big_ops2.cpp:138
size_t sig_words() const
Definition bigint.h:687
BigInt & operator/=(const BigInt &y)
Definition big_ops2.cpp:220
BigInt()=default
BigInt & sub(const word y[], size_t y_words, Sign sign)
Definition bigint.h:358
void set_word_at(size_t i, word w)
Definition bigint.h:608
word * mutable_data()
Definition bigint.h:712
size_t size() const
Definition bigint.h:681
BigInt & rev_sub(const word y[], size_t y_words, secure_vector< word > &ws)
Definition big_ops2.cpp:149
void grow_to(size_t n) const
Definition bigint.h:738
void set_words(const word w[], size_t len)
Definition bigint.h:615
BigInt & operator*=(const BigInt &y)
Definition big_ops2.cpp:160
BigInt & mod_add(const BigInt &y, const BigInt &mod, secure_vector< word > &ws)
Definition big_ops2.cpp:61
int signum() const
Definition bigint.h:493
word word_at(size_t n) const
Definition bigint.h:601
BigInt & operator-=(const BigInt &y)
Definition big_ops2.cpp:23
BigInt & mul(const BigInt &y, secure_vector< word > &ws)
Definition big_ops2.cpp:165
BigInt & mod_sub(const BigInt &y, const BigInt &mod, secure_vector< word > &ws)
Definition big_ops2.cpp:110
size_t bits() const
Definition bigint.cpp:307
BigInt & operator+=(const BigInt &y)
Definition big_ops2.cpp:16
BigInt & operator%=(const BigInt &y)
Definition big_ops2.cpp:232
void clear()
Definition bigint.h:441
const word * _data() const
Definition bigint.h:1033
Sign sign() const
Definition bigint.h:641
BigInt & operator<<=(size_t shift)
Definition big_ops2.cpp:269
BigInt & add(const word y[], size_t y_words, Sign sign)
Definition big_ops2.cpp:32
size_t reduce_below(const BigInt &mod, secure_vector< word > &ws)
Definition bigint.cpp:329
BigInt & square(secure_vector< word > &ws)
Definition big_ops2.cpp:191
void swap_reg(secure_vector< word > &reg)
Definition bigint.h:218
void set_sign(Sign sign)
Definition bigint.h:663
constexpr W vartime_mod_2to1(W n1, W n0) const
Definition mp_core.h:644
constexpr Mask< T > conditional_copy_mem(Mask< T > mask, T *dest, const T *if_set, const T *if_unset, size_t elems)
Definition ct_utils.h:732
constexpr auto bigint_add2(W x[], size_t x_size, const W y[], size_t y_size) -> W
Definition mp_core.h:94
constexpr void bigint_linmul3(W z[], const W x[], size_t x_size, W y)
Definition mp_core.h:416
BOTAN_FORCE_INLINE constexpr bool is_power_of_2(T arg)
Definition bit_ops.h:62
constexpr auto bigint_add3(W z[], const W x[], size_t x_size, const W y[], size_t y_size) -> W
Definition mp_core.h:120
constexpr void bigint_shr1(W x[], size_t x_size, size_t shift)
Definition mp_core.h:331
void bigint_sqr(word z[], size_t z_size, const word x[], size_t x_size, size_t x_sw, word workspace[], size_t ws_size)
Definition mp_karat.cpp:327
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:192
void bigint_mul(word z[], size_t z_size, const word x[], size_t x_size, size_t x_sw, const word y[], size_t y_size, size_t y_sw, word workspace[], size_t ws_size)
Definition mp_karat.cpp:283
constexpr void bigint_shl1(W x[], size_t x_size, size_t x_words, size_t shift)
Definition mp_core.h:309
constexpr int32_t bigint_cmp(const W x[], size_t x_size, const W y[], size_t y_size)
Definition mp_core.h:439
constexpr W bigint_cnd_add(W cnd, W x[], const W y[], size_t size)
Definition mp_core.h:45
void unchecked_copy_memory(T *out, const T *in, size_t n)
Definition mem_utils.h:44
void carry(int64_t &h0, int64_t &h1)
std::vector< T, secure_allocator< T > > secure_vector
Definition secmem.h:128
constexpr auto bigint_sub2(W x[], size_t x_size, const W y[], size_t y_size) -> W
Definition mp_core.h:148
constexpr void bigint_sub2_rev(W x[], const W y[], size_t y_size)
Definition mp_core.h:174
std::conditional_t< HasNative64BitRegisters, std::uint64_t, uint32_t > word
The native machine word, used as the limb type for multiprecision integers.
Definition types.h:131
constexpr auto bigint_linmul2(W x[], size_t x_size, W y) -> W
Definition mp_core.h:405