Coverage Report

Created: 2020-02-14 15:38

/src/botan/src/lib/math/bigint/big_ops2.cpp
Line
Count
Source (jump to first uncovered line)
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
#include <botan/internal/mp_core.h>
10
#include <botan/internal/bit_ops.h>
11
#include <algorithm>
12
13
namespace Botan {
14
15
BigInt& BigInt::add(const word y[], size_t y_words, Sign y_sign)
16
13.2M
   {
17
13.2M
   const size_t x_sw = sig_words();
18
13.2M
19
13.2M
   grow_to(std::max(x_sw, y_words) + 1);
20
13.2M
21
13.2M
   if(sign() == y_sign)
22
10.0M
      {
23
10.0M
      bigint_add2(mutable_data(), size() - 1, y, y_words);
24
10.0M
      }
25
3.11M
   else
26
3.11M
      {
27
3.11M
      const int32_t relative_size = bigint_cmp(data(), x_sw, y, y_words);
28
3.11M
29
3.11M
      if(relative_size >= 0)
30
2.99M
         {
31
2.99M
         // *this >= y
32
2.99M
         bigint_sub2(mutable_data(), x_sw, y, y_words);
33
2.99M
         }
34
115k
      else
35
115k
         {
36
115k
         // *this < y
37
115k
         bigint_sub2_rev(mutable_data(), y, y_words);
38
115k
         }
39
3.11M
40
3.11M
      //this->sign_fixup(relative_size, y_sign);
41
3.11M
      if(relative_size < 0)
42
115k
         set_sign(y_sign);
43
2.99M
      else if(relative_size == 0)
44
2.67k
         set_sign(Positive);
45
3.11M
      }
46
13.2M
47
13.2M
   return (*this);
48
13.2M
   }
49
50
BigInt& BigInt::mod_add(const BigInt& s, const BigInt& mod, secure_vector<word>& ws)
51
11.1M
   {
52
11.1M
   if(this->is_negative() || s.is_negative() || mod.is_negative())
53
0
      throw Invalid_Argument("BigInt::mod_add expects all arguments are positive");
54
11.1M
55
11.1M
   BOTAN_DEBUG_ASSERT(*this < mod);
56
11.1M
   BOTAN_DEBUG_ASSERT(s < mod);
57
11.1M
58
11.1M
   /*
59
11.1M
   t + s or t + s - p == t - (p - s)
60
11.1M
61
11.1M
   So first compute ws = p - s
62
11.1M
63
11.1M
   Then compute t + s and t - ws
64
11.1M
65
11.1M
   If t - ws does not borrow, then that is the correct valued
66
11.1M
   */
67
11.1M
68
11.1M
   const size_t mod_sw = mod.sig_words();
69
11.1M
   BOTAN_ARG_CHECK(mod_sw > 0, "BigInt::mod_add modulus must be positive");
70
11.1M
71
11.1M
   this->grow_to(mod_sw);
72
11.1M
   s.grow_to(mod_sw);
73
11.1M
74
11.1M
   // First mod_sw for p - s, 2*mod_sw for bigint_addsub workspace
75
11.1M
   if(ws.size() < 3*mod_sw)
76
7.09M
      ws.resize(3*mod_sw);
77
11.1M
78
11.1M
   word borrow = bigint_sub3(&ws[0], mod.data(), mod_sw, s.data(), mod_sw);
79
11.1M
   BOTAN_DEBUG_ASSERT(borrow == 0);
80
11.1M
81
11.1M
   // Compute t - ws
82
11.1M
   borrow = bigint_sub3(&ws[mod_sw], this->data(), mod_sw, &ws[0], mod_sw);
83
11.1M
84
11.1M
   // Compute t + s
85
11.1M
   bigint_add3_nc(&ws[mod_sw*2], this->data(), mod_sw, s.data(), mod_sw);
86
11.1M
87
11.1M
   CT::conditional_copy_mem(borrow, &ws[0], &ws[mod_sw*2], &ws[mod_sw], mod_sw);
88
11.1M
   set_words(&ws[0], mod_sw);
89
11.1M
90
11.1M
   return (*this);
91
11.1M
   }
92
93
BigInt& BigInt::mod_sub(const BigInt& s, const BigInt& mod, secure_vector<word>& ws)
94
105M
   {
95
105M
   if(this->is_negative() || s.is_negative() || mod.is_negative())
96
0
      throw Invalid_Argument("BigInt::mod_sub expects all arguments are positive");
97
105M
98
105M
   // We are assuming in this function that *this and s are no more than mod_sw words long
99
105M
   BOTAN_DEBUG_ASSERT(*this < mod);
100
105M
   BOTAN_DEBUG_ASSERT(s < mod);
101
105M
102
105M
   const size_t mod_sw = mod.sig_words();
103
105M
104
105M
   this->grow_to(mod_sw);
105
105M
   s.grow_to(mod_sw);
106
105M
107
105M
   if(ws.size() < mod_sw)
108
0
      ws.resize(mod_sw);
109
105M
110
#if 0
111
   //Faster but not const time:
112
113
   // Compute t - s
114
   word borrow = bigint_sub3(ws.data(), data(), mod_sw, s.data(), mod_sw);
115
116
   if(borrow)
117
      {
118
      // If t < s, instead compute p - (s - t)
119
      bigint_sub2_rev(mutable_data(), s.data(), mod_sw);
120
      bigint_sub2_rev(mutable_data(), mod.data(), mod_sw);
121
      }
122
   else
123
      {
124
      // No borrow so we already have the result we need
125
      swap_reg(ws);
126
      }
127
#else
128
105M
   if(mod_sw == 4)
129
27.3M
      bigint_mod_sub_n<4>(mutable_data(), s.data(), mod.data(), ws.data());
130
78.1M
   else if(mod_sw == 6)
131
24.5M
      bigint_mod_sub_n<6>(mutable_data(), s.data(), mod.data(), ws.data());
132
53.6M
   else
133
53.6M
      bigint_mod_sub(mutable_data(), s.data(), mod.data(), mod_sw, ws.data());
134
105M
#endif
135
105M
136
105M
   return (*this);
137
105M
   }
138
139
BigInt& BigInt::mod_mul(uint8_t y, const BigInt& mod, secure_vector<word>& ws)
140
45.0M
   {
141
45.0M
   BOTAN_ARG_CHECK(this->is_negative() == false, "*this must be positive");
142
45.0M
   BOTAN_ARG_CHECK(y < 16, "y too large");
143
45.0M
144
45.0M
   BOTAN_DEBUG_ASSERT(*this < mod);
145
45.0M
146
45.0M
   *this *= static_cast<word>(y);
147
45.0M
   this->reduce_below(mod, ws);
148
45.0M
   return (*this);
149
45.0M
   }
150
151
BigInt& BigInt::rev_sub(const word y[], size_t y_sw, secure_vector<word>& ws)
152
6.73M
   {
153
6.73M
   if(this->sign() != BigInt::Positive)
154
0
      throw Invalid_State("BigInt::sub_rev requires this is positive");
155
6.73M
156
6.73M
   const size_t x_sw = this->sig_words();
157
6.73M
158
6.73M
   ws.resize(std::max(x_sw, y_sw));
159
6.73M
   clear_mem(ws.data(), ws.size());
160
6.73M
161
6.73M
   const int32_t relative_size = bigint_sub_abs(ws.data(), data(), x_sw, y, y_sw);
162
6.73M
163
6.73M
   this->cond_flip_sign(relative_size > 0);
164
6.73M
   this->swap_reg(ws);
165
6.73M
166
6.73M
   return (*this);
167
6.73M
   }
168
169
/*
170
* Multiplication Operator
171
*/
172
BigInt& BigInt::operator*=(const BigInt& y)
173
0
   {
174
0
   secure_vector<word> ws;
175
0
   return this->mul(y, ws);
176
0
   }
177
178
BigInt& BigInt::mul(const BigInt& y, secure_vector<word>& ws)
179
13.4M
   {
180
13.4M
   const size_t x_sw = sig_words();
181
13.4M
   const size_t y_sw = y.sig_words();
182
13.4M
   set_sign((sign() == y.sign()) ? Positive : Negative);
183
13.4M
184
13.4M
   if(x_sw == 0 || y_sw == 0)
185
1.18M
      {
186
1.18M
      clear();
187
1.18M
      set_sign(Positive);
188
1.18M
      }
189
12.2M
   else if(x_sw == 1 && y_sw)
190
2.24M
      {
191
2.24M
      grow_to(y_sw + 1);
192
2.24M
      bigint_linmul3(mutable_data(), y.data(), y_sw, word_at(0));
193
2.24M
      }
194
10.0M
   else if(y_sw == 1 && x_sw)
195
66
      {
196
66
      word carry = bigint_linmul2(mutable_data(), x_sw, y.word_at(0));
197
66
      set_word_at(x_sw, carry);
198
66
      }
199
10.0M
   else
200
10.0M
      {
201
10.0M
      const size_t new_size = x_sw + y_sw + 1;
202
10.0M
      ws.resize(new_size);
203
10.0M
      secure_vector<word> z_reg(new_size);
204
10.0M
205
10.0M
      bigint_mul(z_reg.data(), z_reg.size(),
206
10.0M
                 data(), size(), x_sw,
207
10.0M
                 y.data(), y.size(), y_sw,
208
10.0M
                 ws.data(), ws.size());
209
10.0M
210
10.0M
      this->swap_reg(z_reg);
211
10.0M
      }
212
13.4M
213
13.4M
   return (*this);
214
13.4M
   }
215
216
BigInt& BigInt::square(secure_vector<word>& ws)
217
4.31M
   {
218
4.31M
   const size_t sw = sig_words();
219
4.31M
220
4.31M
   secure_vector<word> z(2*sw);
221
4.31M
   ws.resize(z.size());
222
4.31M
223
4.31M
   bigint_sqr(z.data(), z.size(),
224
4.31M
              data(), size(), sw,
225
4.31M
              ws.data(), ws.size());
226
4.31M
227
4.31M
   swap_reg(z);
228
4.31M
   set_sign(BigInt::Positive);
229
4.31M
230
4.31M
   return (*this);
231
4.31M
   }
232
233
BigInt& BigInt::operator*=(word y)
234
203M
   {
235
203M
   if(y == 0)
236
0
      {
237
0
      clear();
238
0
      set_sign(Positive);
239
0
      }
240
203M
241
203M
   const word carry = bigint_linmul2(mutable_data(), size(), y);
242
203M
   set_word_at(size(), carry);
243
203M
244
203M
   return (*this);
245
203M
   }
246
247
/*
248
* Division Operator
249
*/
250
BigInt& BigInt::operator/=(const BigInt& y)
251
0
   {
252
0
   if(y.sig_words() == 1 && is_power_of_2(y.word_at(0)))
253
0
      (*this) >>= (y.bits() - 1);
254
0
   else
255
0
      (*this) = (*this) / y;
256
0
   return (*this);
257
0
   }
258
259
/*
260
* Modulo Operator
261
*/
262
BigInt& BigInt::operator%=(const BigInt& mod)
263
2.58M
   {
264
2.58M
   return (*this = (*this) % mod);
265
2.58M
   }
266
267
/*
268
* Modulo Operator
269
*/
270
word BigInt::operator%=(word mod)
271
0
   {
272
0
   if(mod == 0)
273
0
      throw BigInt::DivideByZero();
274
0
275
0
   word remainder = 0;
276
0
277
0
   if(is_power_of_2(mod))
278
0
       {
279
0
       remainder = (word_at(0) & (mod - 1));
280
0
       }
281
0
   else
282
0
      {
283
0
      const size_t sw = sig_words();
284
0
      for(size_t i = sw; i > 0; --i)
285
0
         remainder = bigint_modop(remainder, word_at(i-1), mod);
286
0
      }
287
0
288
0
   if(remainder && sign() == BigInt::Negative)
289
0
      remainder = mod - remainder;
290
0
291
0
   m_data.set_to_zero();
292
0
   m_data.set_word_at(0, remainder);
293
0
   set_sign(BigInt::Positive);
294
0
   return remainder;
295
0
   }
296
297
/*
298
* Left Shift Operator
299
*/
300
BigInt& BigInt::operator<<=(size_t shift)
301
5.15M
   {
302
5.15M
   const size_t shift_words = shift / BOTAN_MP_WORD_BITS;
303
5.15M
   const size_t shift_bits  = shift % BOTAN_MP_WORD_BITS;
304
5.15M
   const size_t size = sig_words();
305
5.15M
306
5.15M
   const size_t bits_free = top_bits_free();
307
5.15M
308
5.15M
   const size_t new_size = size + shift_words + (bits_free < shift_bits);
309
5.15M
310
5.15M
   m_data.grow_to(new_size);
311
5.15M
312
5.15M
   bigint_shl1(m_data.mutable_data(), new_size, size, shift_words, shift_bits);
313
5.15M
314
5.15M
   return (*this);
315
5.15M
   }
316
317
/*
318
* Right Shift Operator
319
*/
320
BigInt& BigInt::operator>>=(size_t shift)
321
25.0M
   {
322
25.0M
   const size_t shift_words = shift / BOTAN_MP_WORD_BITS;
323
25.0M
   const size_t shift_bits  = shift % BOTAN_MP_WORD_BITS;
324
25.0M
325
25.0M
   bigint_shr1(m_data.mutable_data(), m_data.size(), shift_words, shift_bits);
326
25.0M
327
25.0M
   if(is_negative() && is_zero())
328
0
      set_sign(Positive);
329
25.0M
330
25.0M
   return (*this);
331
25.0M
   }
332
333
}