Botan 3.4.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 bigint_add2(mutable_data(), size() - 1, y, y_words);
23 } else {
24 const int32_t relative_size = bigint_cmp(data(), x_sw, y, y_words);
25
26 if(relative_size >= 0) {
27 // *this >= y
28 bigint_sub2(mutable_data(), x_sw, y, y_words);
29 } else {
30 // *this < y
31 bigint_sub2_rev(mutable_data(), y, y_words);
32 }
33
34 //this->sign_fixup(relative_size, y_sign);
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 word borrow = bigint_sub3(&ws[0], mod.data(), mod_sw, s.data(), mod_sw);
75 BOTAN_DEBUG_ASSERT(borrow == 0);
76 BOTAN_UNUSED(borrow);
77
78 // Compute t - ws
79 borrow = bigint_sub3(&ws[mod_sw], this->data(), mod_sw, &ws[0], mod_sw);
80
81 // Compute t + s
82 bigint_add3_nc(&ws[mod_sw * 2], this->data(), mod_sw, s.data(), mod_sw);
83
84 CT::conditional_copy_mem(borrow, &ws[0], &ws[mod_sw * 2], &ws[mod_sw], mod_sw);
85 set_words(&ws[0], mod_sw);
86
87 return (*this);
88}
89
91 if(this->is_negative() || s.is_negative() || mod.is_negative()) {
92 throw Invalid_Argument("BigInt::mod_sub expects all arguments are positive");
93 }
94
95 // We are assuming in this function that *this and s are no more than mod_sw words long
96 BOTAN_DEBUG_ASSERT(*this < mod);
97 BOTAN_DEBUG_ASSERT(s < mod);
98
99 const size_t mod_sw = mod.sig_words();
100
101 this->grow_to(mod_sw);
102 s.grow_to(mod_sw);
103
104 if(ws.size() < mod_sw) {
105 ws.resize(mod_sw);
106 }
107
108 if(mod_sw == 4) {
109 bigint_mod_sub_n<4>(mutable_data(), s.data(), mod.data(), ws.data());
110 } else if(mod_sw == 6) {
111 bigint_mod_sub_n<6>(mutable_data(), s.data(), mod.data(), ws.data());
112 } else {
113 bigint_mod_sub(mutable_data(), s.data(), mod.data(), mod_sw, ws.data());
114 }
115
116 return (*this);
117}
118
119BigInt& BigInt::mod_mul(uint8_t y, const BigInt& mod, secure_vector<word>& ws) {
120 BOTAN_ARG_CHECK(this->is_negative() == false, "*this must be positive");
121 BOTAN_ARG_CHECK(y < 16, "y too large");
122
123 BOTAN_DEBUG_ASSERT(*this < mod);
124
125 *this *= static_cast<word>(y);
126 this->reduce_below(mod, ws);
127 return (*this);
128}
129
130BigInt& BigInt::rev_sub(const word y[], size_t y_sw, secure_vector<word>& ws) {
131 if(this->sign() != BigInt::Positive) {
132 throw Invalid_State("BigInt::sub_rev requires this is positive");
133 }
134
135 const size_t x_sw = this->sig_words();
136
137 ws.resize(std::max(x_sw, y_sw));
138 clear_mem(ws.data(), ws.size());
139
140 const int32_t relative_size = bigint_sub_abs(ws.data(), data(), x_sw, y, y_sw);
141
142 this->cond_flip_sign(relative_size > 0);
143 this->swap_reg(ws);
144
145 return (*this);
146}
147
148/*
149* Multiplication Operator
150*/
153 return this->mul(y, ws);
154}
155
157 const size_t x_sw = sig_words();
158 const size_t y_sw = y.sig_words();
159 set_sign((sign() == y.sign()) ? Positive : Negative);
160
161 if(x_sw == 0 || y_sw == 0) {
162 clear();
164 } else if(x_sw == 1 && y_sw) {
165 grow_to(y_sw + 1);
166 bigint_linmul3(mutable_data(), y.data(), y_sw, word_at(0));
167 } else if(y_sw == 1 && x_sw) {
168 word carry = bigint_linmul2(mutable_data(), x_sw, y.word_at(0));
169 set_word_at(x_sw, carry);
170 } else {
171 const size_t new_size = x_sw + y_sw + 1;
172 ws.resize(new_size);
173 secure_vector<word> z_reg(new_size);
174
175 bigint_mul(z_reg.data(), z_reg.size(), data(), size(), x_sw, y.data(), y.size(), y_sw, ws.data(), ws.size());
176
177 this->swap_reg(z_reg);
178 }
179
180 return (*this);
181}
182
184 const size_t sw = sig_words();
185
186 secure_vector<word> z(2 * sw);
187 ws.resize(z.size());
188
189 bigint_sqr(z.data(), z.size(), data(), size(), sw, ws.data(), ws.size());
190
191 swap_reg(z);
193
194 return (*this);
195}
196
198 if(y == 0) {
199 clear();
201 }
202
203 const word carry = bigint_linmul2(mutable_data(), size(), y);
205
206 return (*this);
207}
208
209/*
210* Division Operator
211*/
213 if(y.sig_words() == 1 && is_power_of_2(y.word_at(0))) {
214 (*this) >>= (y.bits() - 1);
215 } else {
216 (*this) = (*this) / y;
217 }
218 return (*this);
219}
220
221/*
222* Modulo Operator
223*/
225 return (*this = (*this) % mod);
226}
227
228/*
229* Modulo Operator
230*/
231word BigInt::operator%=(word mod) {
232 if(mod == 0) {
233 throw Invalid_Argument("BigInt::operator%= divide by zero");
234 }
235
236 word remainder = 0;
237
238 if(is_power_of_2(mod)) {
239 remainder = (word_at(0) & (mod - 1));
240 } else {
241 const size_t sw = sig_words();
242 for(size_t i = sw; i > 0; --i) {
243 remainder = bigint_modop_vartime(remainder, word_at(i - 1), mod);
244 }
245 }
246
247 if(remainder && sign() == BigInt::Negative) {
248 remainder = mod - remainder;
249 }
250
251 m_data.set_to_zero();
252 m_data.set_word_at(0, remainder);
254 return remainder;
255}
256
257/*
258* Left Shift Operator
259*/
261 const size_t sw = sig_words();
262 const size_t new_size = sw + (shift + BOTAN_MP_WORD_BITS - 1) / BOTAN_MP_WORD_BITS;
263
264 m_data.grow_to(new_size);
265
266 bigint_shl1(m_data.mutable_data(), new_size, sw, shift);
267
268 return (*this);
269}
270
271/*
272* Right Shift Operator
273*/
275 bigint_shr1(m_data.mutable_data(), m_data.size(), shift);
276
277 if(is_negative() && is_zero()) {
279 }
280
281 return (*this);
282}
283
284} // namespace Botan
#define BOTAN_UNUSED
Definition assert.h:118
#define BOTAN_DEBUG_ASSERT(expr)
Definition assert.h:98
#define BOTAN_ARG_CHECK(expr, msg)
Definition assert.h:29
BigInt & operator>>=(size_t shift)
Definition big_ops2.cpp:274
BigInt & mod_mul(uint8_t y, const BigInt &mod, secure_vector< word > &ws)
Definition big_ops2.cpp:119
size_t sig_words() const
Definition bigint.h:584
BigInt & operator/=(const BigInt &y)
Definition big_ops2.cpp:212
void set_word_at(size_t i, word w)
Definition bigint.h:520
word * mutable_data()
Definition bigint.h:609
size_t size() const
Definition bigint.h:578
BigInt & rev_sub(const word y[], size_t y_words, secure_vector< word > &ws)
Definition big_ops2.cpp:130
void grow_to(size_t n) const
Definition bigint.h:631
void set_words(const word w[], size_t len)
Definition bigint.h:522
BigInt & operator*=(const BigInt &y)
Definition big_ops2.cpp:151
BigInt & mod_add(const BigInt &y, const BigInt &mod, secure_vector< word > &ws)
Definition big_ops2.cpp:45
const word * data() const
Definition bigint.h:615
word word_at(size_t n) const
Definition bigint.h:518
BigInt & mul(const BigInt &y, secure_vector< word > &ws)
Definition big_ops2.cpp:156
void cond_flip_sign(bool predicate)
Definition bigint.cpp:475
BigInt & mod_sub(const BigInt &y, const BigInt &mod, secure_vector< word > &ws)
Definition big_ops2.cpp:90
size_t bits() const
Definition bigint.cpp:290
BigInt & operator%=(const BigInt &y)
Definition big_ops2.cpp:224
void clear()
Definition bigint.h:370
Sign sign() const
Definition bigint.h:540
BigInt & operator<<=(size_t shift)
Definition big_ops2.cpp:260
BigInt & add(const word y[], size_t y_words, Sign sign)
Definition big_ops2.cpp:16
bool is_zero() const
Definition bigint.h:428
size_t reduce_below(const BigInt &mod, secure_vector< word > &ws)
Definition bigint.cpp:312
BigInt & square(secure_vector< word > &ws)
Definition big_ops2.cpp:183
bool is_negative() const
Definition bigint.h:528
void swap_reg(secure_vector< word > &reg)
Definition bigint.h:177
void set_sign(Sign sign)
Definition bigint.h:561
#define BOTAN_MP_WORD_BITS
Definition build.h:50
constexpr Mask< T > conditional_copy_mem(Mask< T > mask, T *to, const T *from0, const T *from1, size_t elems)
Definition ct_utils.h:292
constexpr void bigint_linmul3(W z[], const W x[], size_t x_size, W y)
Definition mp_core.h:558
constexpr bool is_power_of_2(T arg)
Definition bit_ops.h:45
constexpr void bigint_shr1(W x[], size_t x_size, size_t shift)
Definition mp_core.h:475
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:326
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:335
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:282
constexpr void bigint_shl1(W x[], size_t x_size, size_t x_words, size_t shift)
Definition mp_core.h:456
constexpr int32_t bigint_cmp(const W x[], size_t x_size, const W y[], size_t y_size)
Definition mp_core.h:581
void carry(int64_t &h0, int64_t &h1)
constexpr auto bigint_modop_vartime(W n1, W n0, W d) -> W
Definition mp_core.h:802
constexpr auto bigint_sub_abs(W z[], const W x[], const W y[], size_t N, W ws[]) -> CT::Mask< W >
Definition mp_core.h:428
constexpr void bigint_add2(W x[], size_t x_size, const W y[], size_t y_size)
Definition mp_core.h:269
std::vector< T, secure_allocator< T > > secure_vector
Definition secmem.h:61
constexpr auto bigint_sub2(W x[], size_t x_size, const W y[], size_t y_size) -> W
Definition mp_core.h:285
constexpr void bigint_sub2_rev(W x[], const W y[], size_t y_size)
Definition mp_core.h:311
constexpr void clear_mem(T *ptr, size_t n)
Definition mem_ops.h:120
constexpr void bigint_mod_sub(W t[], const W s[], const W mod[], size_t mod_sw, W ws[])
Definition mp_core.h:728
constexpr auto bigint_add3_nc(W z[], const W x[], size_t x_size, const W y[], size_t y_size) -> W
Definition mp_core.h:237
constexpr auto bigint_linmul2(W x[], size_t x_size, W y) -> W
Definition mp_core.h:541