Botan 3.9.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/internal/bit_ops.h>
11#include <botan/internal/mp_core.h>
12#include <algorithm>
13
14namespace Botan {
15
16BigInt& BigInt::add(const word y[], size_t y_words, Sign y_sign) {
17 const size_t x_sw = sig_words();
18
19 grow_to(std::max(x_sw, y_words) + 1);
20
21 if(sign() == y_sign) {
22 word carry = bigint_add2(mutable_data(), size() - 1, y, y_words);
23 mutable_data()[size() - 1] += carry;
24 } else {
25 const int32_t relative_size = bigint_cmp(_data(), x_sw, y, y_words);
26
27 if(relative_size >= 0) {
28 // *this >= y
29 bigint_sub2(mutable_data(), x_sw, y, y_words);
30 } else {
31 // *this < y: compute *this = y - *this
32 bigint_sub2_rev(mutable_data(), y, y_words);
33 }
34
35 if(relative_size < 0) {
36 set_sign(y_sign);
37 } else if(relative_size == 0) {
39 }
40 }
41
42 return (*this);
43}
44
46 if(this->is_negative() || s.is_negative() || mod.is_negative()) {
47 throw Invalid_Argument("BigInt::mod_add expects all arguments are positive");
48 }
49
50 BOTAN_DEBUG_ASSERT(*this < mod);
51 BOTAN_DEBUG_ASSERT(s < mod);
52
53 /*
54 t + s or t + s - p == t - (p - s)
55
56 So first compute ws = p - s
57
58 Then compute t + s and t - ws
59
60 If t - ws does not borrow, then that is the correct valued
61 */
62
63 const size_t mod_sw = mod.sig_words();
64 BOTAN_ARG_CHECK(mod_sw > 0, "BigInt::mod_add modulus must be positive");
65
66 this->grow_to(mod_sw);
67 s.grow_to(mod_sw);
68
69 // First mod_sw for p - s, 2*mod_sw for bigint_addsub workspace
70 if(ws.size() < 3 * mod_sw) {
71 ws.resize(3 * mod_sw);
72 }
73
74 // NOLINTBEGIN(readability-container-data-pointer)
75
76 word borrow = bigint_sub3(&ws[0], mod._data(), mod_sw, s._data(), mod_sw);
77 BOTAN_DEBUG_ASSERT(borrow == 0);
78 BOTAN_UNUSED(borrow);
79
80 // Compute t - ws
81 borrow = bigint_sub3(&ws[mod_sw], this->_data(), mod_sw, &ws[0], mod_sw);
82
83 // Compute t + s
84 bigint_add3(&ws[mod_sw * 2], this->_data(), mod_sw, s._data(), mod_sw);
85
86 CT::conditional_copy_mem(borrow, &ws[0], &ws[mod_sw * 2], &ws[mod_sw], mod_sw);
87 set_words(&ws[0], mod_sw);
88
89 // NOLINTEND(readability-container-data-pointer)
90
91 return (*this);
92}
93
95 if(this->is_negative() || s.is_negative() || mod.is_negative()) {
96 throw Invalid_Argument("BigInt::mod_sub expects all arguments are positive");
97 }
98
99 // We are assuming in this function that *this and s are no more than mod_sw words long
100 BOTAN_DEBUG_ASSERT(*this < mod);
101 BOTAN_DEBUG_ASSERT(s < mod);
102
103 const size_t mod_sw = mod.sig_words();
104
105 this->grow_to(mod_sw);
106 s.grow_to(mod_sw);
107
108 if(ws.size() < mod_sw) {
109 ws.resize(mod_sw);
110 }
111
112 const word borrow = bigint_sub3(ws.data(), mutable_data(), mod_sw, s._data(), mod_sw);
113
114 // Conditionally add back the modulus
115 bigint_cnd_add(borrow, ws.data(), mod._data(), mod_sw);
116
117 copy_mem(mutable_data(), ws.data(), mod_sw);
118
119 return (*this);
120}
121
122BigInt& BigInt::mod_mul(uint8_t y, const BigInt& mod, secure_vector<word>& ws) {
123 BOTAN_ARG_CHECK(this->is_negative() == false, "*this must be positive");
124 BOTAN_ARG_CHECK(y < 16, "y too large");
125
126 BOTAN_DEBUG_ASSERT(*this < mod);
127
128 *this *= static_cast<word>(y);
129 this->reduce_below(mod, ws);
130 return (*this);
131}
132
133BigInt& BigInt::rev_sub(const word y[], size_t y_sw, secure_vector<word>& ws) {
134 BOTAN_UNUSED(ws);
135 BigInt y_bn;
136 y_bn.m_data.set_words(y, y_sw);
137 *this = y_bn - *this;
138 return (*this);
139}
140
141/*
142* Multiplication Operator
143*/
146 return this->mul(y, ws);
147}
148
150 const size_t x_sw = sig_words();
151 const size_t y_sw = y.sig_words();
152 set_sign((sign() == y.sign()) ? Positive : Negative);
153
154 if(x_sw == 0 || y_sw == 0) {
155 clear();
157 } else if(x_sw == 1 && y_sw > 0) {
158 grow_to(y_sw + 1);
159 bigint_linmul3(mutable_data(), y._data(), y_sw, word_at(0));
160 } else {
161 const size_t new_size = x_sw + y_sw + 1;
162 if(ws.size() < new_size) {
163 ws.resize(new_size);
164 }
165 secure_vector<word> z_reg(new_size);
166
167 bigint_mul(z_reg.data(), z_reg.size(), _data(), size(), x_sw, y._data(), y.size(), y_sw, ws.data(), ws.size());
168
169 this->swap_reg(z_reg);
170 }
171
172 return (*this);
173}
174
176 const size_t sw = sig_words();
177
178 secure_vector<word> z(2 * sw);
179 ws.resize(z.size());
180
181 bigint_sqr(z.data(), z.size(), _data(), size(), sw, ws.data(), ws.size());
182
183 swap_reg(z);
185
186 return (*this);
187}
188
190 if(y == 0) {
191 clear();
193 }
194
195 const word carry = bigint_linmul2(mutable_data(), size(), y);
197
198 return (*this);
199}
200
201/*
202* Division Operator
203*/
205 if(y.sig_words() == 1 && is_power_of_2(y.word_at(0))) {
206 (*this) >>= (y.bits() - 1);
207 } else {
208 (*this) = (*this) / y;
209 }
210 return (*this);
211}
212
213/*
214* Modulo Operator
215*/
217 return (*this = (*this) % mod);
218}
219
220/*
221* Modulo Operator
222*/
224 if(mod == 0) {
225 throw Invalid_Argument("BigInt::operator%= divide by zero");
226 }
227
228 word remainder = 0;
229
230 if(is_power_of_2(mod)) {
231 remainder = (word_at(0) & (mod - 1));
232 } else {
233 const size_t sw = sig_words();
234 for(size_t i = sw; i > 0; --i) {
235 remainder = bigint_modop_vartime(remainder, word_at(i - 1), mod);
236 }
237 }
238
239 if(remainder != 0 && sign() == BigInt::Negative) {
240 remainder = mod - remainder;
241 }
242
243 m_data.set_to_zero();
244 m_data.set_word_at(0, remainder);
246 return remainder;
247}
248
249/*
250* Left Shift Operator
251*/
253 const size_t sw = sig_words();
254 const size_t new_size = sw + (shift + WordInfo<word>::bits - 1) / WordInfo<word>::bits;
255
256 m_data.grow_to(new_size);
257
258 bigint_shl1(m_data.mutable_data(), new_size, sw, shift);
259
260 return (*this);
261}
262
263/*
264* Right Shift Operator
265*/
267 bigint_shr1(m_data.mutable_data(), m_data.size(), shift);
268
269 if(is_negative() && is_zero()) {
271 }
272
273 return (*this);
274}
275
276} // 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:266
BigInt & mod_mul(uint8_t y, const BigInt &mod, secure_vector< word > &ws)
Definition big_ops2.cpp:122
size_t sig_words() const
Definition bigint.h:615
BigInt & operator/=(const BigInt &y)
Definition big_ops2.cpp:204
BigInt()=default
void set_word_at(size_t i, word w)
Definition bigint.h:549
word * mutable_data()
Definition bigint.h:640
size_t size() const
Definition bigint.h:609
BigInt & rev_sub(const word y[], size_t y_words, secure_vector< word > &ws)
Definition big_ops2.cpp:133
void grow_to(size_t n) const
Definition bigint.h:666
void set_words(const word w[], size_t len)
Definition bigint.h:551
BigInt & operator*=(const BigInt &y)
Definition big_ops2.cpp:144
BigInt & mod_add(const BigInt &y, const BigInt &mod, secure_vector< word > &ws)
Definition big_ops2.cpp:45
word word_at(size_t n) const
Definition bigint.h:547
BigInt & mul(const BigInt &y, secure_vector< word > &ws)
Definition big_ops2.cpp:149
BigInt & mod_sub(const BigInt &y, const BigInt &mod, secure_vector< word > &ws)
Definition big_ops2.cpp:94
size_t bits() const
Definition bigint.cpp:311
BigInt & operator%=(const BigInt &y)
Definition big_ops2.cpp:216
void clear()
Definition bigint.h:399
const word * _data() const
Definition bigint.h:936
Sign sign() const
Definition bigint.h:571
BigInt & operator<<=(size_t shift)
Definition big_ops2.cpp:252
BigInt & add(const word y[], size_t y_words, Sign sign)
Definition big_ops2.cpp:16
bool is_zero() const
Definition bigint.h:457
size_t reduce_below(const BigInt &mod, secure_vector< word > &ws)
Definition bigint.cpp:333
BigInt & square(secure_vector< word > &ws)
Definition big_ops2.cpp:175
bool is_negative() const
Definition bigint.h:559
void swap_reg(secure_vector< word > &reg)
Definition bigint.h:198
void set_sign(Sign sign)
Definition bigint.h:592
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:760
constexpr auto bigint_add2(W x[], size_t x_size, const W y[], size_t y_size) -> W
Definition mp_core.h:96
constexpr void bigint_linmul3(W z[], const W x[], size_t x_size, W y)
Definition mp_core.h:405
BOTAN_FORCE_INLINE constexpr bool is_power_of_2(T arg)
Definition bit_ops.h:45
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:122
constexpr void copy_mem(T *out, const T *in, size_t n)
Definition mem_ops.h:145
constexpr void bigint_shr1(W x[], size_t x_size, size_t shift)
Definition mp_core.h:328
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:194
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:428
constexpr W bigint_cnd_add(W cnd, W x[], const W y[], size_t size)
Definition mp_core.h:47
void carry(int64_t &h0, int64_t &h1)
constexpr auto bigint_modop_vartime(W n1, W n0, W d) -> W
Definition mp_core.h:568
std::vector< T, secure_allocator< T > > secure_vector
Definition secmem.h:69
constexpr auto bigint_sub2(W x[], size_t x_size, const W y[], size_t y_size) -> W
Definition mp_core.h:150
constexpr void bigint_sub2_rev(W x[], const W y[], size_t y_size)
Definition mp_core.h:176
std::conditional_t< HasNative64BitRegisters, std::uint64_t, uint32_t > word
Definition types.h:119
constexpr auto bigint_linmul2(W x[], size_t x_size, W y) -> W
Definition mp_core.h:394