Coverage Report

Created: 2020-09-16 07:52

/src/botan/src/lib/math/bigint/bigint.cpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
* BigInt Base
3
* (C) 1999-2011,2012,2014,2019 Jack Lloyd
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/rounding.h>
11
#include <botan/internal/bit_ops.h>
12
#include <botan/internal/ct_utils.h>
13
#include <botan/loadstor.h>
14
15
namespace Botan {
16
17
BigInt::BigInt(const word words[], size_t length)
18
88.7k
   {
19
88.7k
   m_data.set_words(words, length);
20
88.7k
   }
21
22
/*
23
* Construct a BigInt from a regular number
24
*/
25
BigInt::BigInt(uint64_t n)
26
5.63M
   {
27
5.63M
   if(n > 0)
28
2.75M
      {
29
#if BOTAN_MP_WORD_BITS == 32
30
      m_data.set_word_at(0, static_cast<word>(n));
31
      m_data.set_word_at(1, static_cast<word>(n >> 32));
32
#else
33
2.75M
      m_data.set_word_at(0, n);
34
2.75M
#endif
35
2.75M
      }
36
5.63M
37
5.63M
   }
38
39
/*
40
* Construct a BigInt of the specified size
41
*/
42
BigInt::BigInt(Sign s, size_t size)
43
17.5M
   {
44
17.5M
   m_data.set_size(size);
45
17.5M
   m_signedness = s;
46
17.5M
   }
47
48
/*
49
* Construct a BigInt from a string
50
*/
51
BigInt::BigInt(const std::string& str)
52
18.2k
   {
53
18.2k
   Base base = Decimal;
54
18.2k
   size_t markers = 0;
55
18.2k
   bool negative = false;
56
18.2k
57
18.2k
   if(str.length() > 0 && str[0] == '-')
58
0
      {
59
0
      markers += 1;
60
0
      negative = true;
61
0
      }
62
18.2k
63
18.2k
   if(str.length() > markers + 2 && str[markers    ] == '0' &&
64
18.2k
                                    str[markers + 1] == 'x')
65
18.2k
      {
66
18.2k
      markers += 2;
67
18.2k
      base = Hexadecimal;
68
18.2k
      }
69
18.2k
70
18.2k
   *this = decode(cast_char_ptr_to_uint8(str.data()) + markers,
71
18.2k
                  str.length() - markers, base);
72
18.2k
73
18.2k
   if(negative) set_sign(Negative);
74
18.2k
   else         set_sign(Positive);
75
18.2k
   }
76
77
BigInt::BigInt(const uint8_t input[], size_t length)
78
108k
   {
79
108k
   binary_decode(input, length);
80
108k
   }
81
82
/*
83
* Construct a BigInt from an encoded BigInt
84
*/
85
BigInt::BigInt(const uint8_t input[], size_t length, Base base)
86
0
   {
87
0
   *this = decode(input, length, base);
88
0
   }
89
90
BigInt::BigInt(const uint8_t buf[], size_t length, size_t max_bits)
91
442
   {
92
442
   const size_t max_bytes = std::min(length, (max_bits + 7) / 8);
93
442
   binary_decode(buf, max_bytes);
94
442
95
442
   const size_t b = this->bits();
96
442
   if(b > max_bits)
97
0
      {
98
0
      *this >>= (b - max_bits);
99
0
      }
100
442
   }
101
102
/*
103
* Construct a BigInt from an encoded BigInt
104
*/
105
BigInt::BigInt(RandomNumberGenerator& rng, size_t bits, bool set_high_bit)
106
53.1k
   {
107
53.1k
   randomize(rng, bits, set_high_bit);
108
53.1k
   }
109
110
uint8_t BigInt::byte_at(size_t n) const
111
68.6k
   {
112
68.6k
   return get_byte(sizeof(word) - (n % sizeof(word)) - 1,
113
68.6k
                   word_at(n / sizeof(word)));
114
68.6k
   }
115
116
int32_t BigInt::cmp_word(word other) const
117
7.10M
   {
118
7.10M
   if(is_negative())
119
8.52k
      return -1; // other is positive ...
120
7.09M
121
7.09M
   const size_t sw = this->sig_words();
122
7.09M
   if(sw > 1)
123
6.44M
      return 1; // must be larger since other is just one word ...
124
652k
125
652k
   return bigint_cmp(this->data(), sw, &other, 1);
126
652k
   }
127
128
/*
129
* Comparison Function
130
*/
131
int32_t BigInt::cmp(const BigInt& other, bool check_signs) const
132
656k
   {
133
656k
   if(check_signs)
134
656k
      {
135
656k
      if(other.is_positive() && this->is_negative())
136
0
         return -1;
137
656k
138
656k
      if(other.is_negative() && this->is_positive())
139
1
         return 1;
140
656k
141
656k
      if(other.is_negative() && this->is_negative())
142
0
         return (-bigint_cmp(this->data(), this->size(),
143
0
                             other.data(), other.size()));
144
656k
      }
145
656k
146
656k
   return bigint_cmp(this->data(), this->size(),
147
656k
                     other.data(), other.size());
148
656k
   }
149
150
bool BigInt::is_equal(const BigInt& other) const
151
262k
   {
152
262k
   if(this->sign() != other.sign())
153
0
      return false;
154
262k
155
262k
   return bigint_ct_is_eq(this->data(), this->sig_words(),
156
262k
                          other.data(), other.sig_words()).is_set();
157
262k
   }
158
159
bool BigInt::is_less_than(const BigInt& other) const
160
5.69M
   {
161
5.69M
   if(this->is_negative() && other.is_positive())
162
78
      return true;
163
5.69M
164
5.69M
   if(this->is_positive() && other.is_negative())
165
0
      return false;
166
5.69M
167
5.69M
   if(other.is_negative() && this->is_negative())
168
0
      {
169
0
      return !bigint_ct_is_lt(other.data(), other.sig_words(),
170
0
                              this->data(), this->sig_words(), true).is_set();
171
0
      }
172
5.69M
173
5.69M
   return bigint_ct_is_lt(this->data(), this->sig_words(),
174
5.69M
                          other.data(), other.sig_words()).is_set();
175
5.69M
   }
176
177
void BigInt::encode_words(word out[], size_t size) const
178
3.72M
   {
179
3.72M
   const size_t words = sig_words();
180
3.72M
181
3.72M
   if(words > size)
182
0
      throw Encoding_Error("BigInt::encode_words value too large to encode");
183
3.72M
184
3.72M
   clear_mem(out, size);
185
3.72M
   copy_mem(out, data(), words);
186
3.72M
   }
187
188
size_t BigInt::Data::calc_sig_words() const
189
140M
   {
190
140M
   const size_t sz = m_reg.size();
191
140M
   size_t sig = sz;
192
140M
193
140M
   word sub = 1;
194
140M
195
4.29G
   for(size_t i = 0; i != sz; ++i)
196
4.15G
      {
197
4.15G
      const word w = m_reg[sz - i - 1];
198
4.15G
      sub &= ct_is_zero(w);
199
4.15G
      sig -= sub;
200
4.15G
      }
201
140M
202
   /*
203
   * This depends on the data so is poisoned, but unpoison it here as
204
   * later conditionals are made on the size.
205
   */
206
140M
   CT::unpoison(sig);
207
140M
208
140M
   return sig;
209
140M
   }
210
211
/*
212
* Return bits {offset...offset+length}
213
*/
214
uint32_t BigInt::get_substring(size_t offset, size_t length) const
215
12.8M
   {
216
12.8M
   if(length == 0 || length > 32)
217
0
      throw Invalid_Argument("BigInt::get_substring invalid substring length");
218
12.8M
219
12.8M
   const uint32_t mask = 0xFFFFFFFF >> (32 - length);
220
12.8M
221
12.8M
   const size_t word_offset = offset / BOTAN_MP_WORD_BITS;
222
12.8M
   const size_t wshift = (offset % BOTAN_MP_WORD_BITS);
223
12.8M
224
   /*
225
   * The substring is contained within one or at most two words. The
226
   * offset and length are not secret, so we can perform conditional
227
   * operations on those values.
228
   */
229
12.8M
   const word w0 = word_at(word_offset);
230
12.8M
231
12.8M
   if(wshift == 0 || (offset + length) / BOTAN_MP_WORD_BITS == word_offset)
232
12.1M
      {
233
12.1M
      return static_cast<uint32_t>(w0 >> wshift) & mask;
234
12.1M
      }
235
668k
   else
236
668k
      {
237
668k
      const word w1 = word_at(word_offset + 1);
238
668k
      return static_cast<uint32_t>((w0 >> wshift) | (w1 << (BOTAN_MP_WORD_BITS - wshift))) & mask;
239
668k
      }
240
12.8M
   }
241
242
/*
243
* Convert this number to a uint32_t, if possible
244
*/
245
uint32_t BigInt::to_u32bit() const
246
0
   {
247
0
   if(is_negative())
248
0
      throw Encoding_Error("BigInt::to_u32bit: Number is negative");
249
0
   if(bits() > 32)
250
0
      throw Encoding_Error("BigInt::to_u32bit: Number is too big to convert");
251
0
252
0
   uint32_t out = 0;
253
0
   for(size_t i = 0; i != 4; ++i)
254
0
      out = (out << 8) | byte_at(3-i);
255
0
   return out;
256
0
   }
257
258
/*
259
* Set bit number n
260
*/
261
void BigInt::conditionally_set_bit(size_t n, bool set_it)
262
315M
   {
263
315M
   const size_t which = n / BOTAN_MP_WORD_BITS;
264
315M
   const word mask = static_cast<word>(set_it) << (n % BOTAN_MP_WORD_BITS);
265
315M
   m_data.set_word_at(which, word_at(which) | mask);
266
315M
   }
267
268
/*
269
* Clear bit number n
270
*/
271
void BigInt::clear_bit(size_t n)
272
0
   {
273
0
   const size_t which = n / BOTAN_MP_WORD_BITS;
274
0
275
0
   if(which < size())
276
0
      {
277
0
      const word mask = ~(static_cast<word>(1) << (n % BOTAN_MP_WORD_BITS));
278
0
      m_data.set_word_at(which, word_at(which) & mask);
279
0
      }
280
0
   }
281
282
size_t BigInt::bytes() const
283
197k
   {
284
197k
   return round_up(bits(), 8) / 8;
285
197k
   }
286
287
size_t BigInt::top_bits_free() const
288
11.2M
   {
289
11.2M
   const size_t words = sig_words();
290
11.2M
291
11.2M
   const word top_word = word_at(words - 1);
292
11.2M
   const size_t bits_used = high_bit(top_word);
293
11.2M
   CT::unpoison(bits_used);
294
11.2M
   return BOTAN_MP_WORD_BITS - bits_used;
295
11.2M
   }
296
297
size_t BigInt::bits() const
298
3.37M
   {
299
3.37M
   const size_t words = sig_words();
300
3.37M
301
3.37M
   if(words == 0)
302
13.4k
      return 0;
303
3.36M
304
3.36M
   const size_t full_words = (words - 1) * BOTAN_MP_WORD_BITS;
305
3.36M
   const size_t top_bits = BOTAN_MP_WORD_BITS - top_bits_free();
306
3.36M
307
3.36M
   return full_words + top_bits;
308
3.36M
   }
309
310
/*
311
* Calcluate the size in a certain base
312
*/
313
size_t BigInt::encoded_size(Base base) const
314
0
   {
315
0
   static const double LOG_2_BASE_10 = 0.30102999566;
316
0
317
0
   if(base == Binary)
318
0
      return bytes();
319
0
   else if(base == Hexadecimal)
320
0
      return 2*bytes();
321
0
   else if(base == Decimal)
322
0
      return static_cast<size_t>((bits() * LOG_2_BASE_10) + 1);
323
0
   else
324
0
      throw Invalid_Argument("Unknown base for BigInt encoding");
325
0
   }
326
327
/*
328
* Return the negation of this number
329
*/
330
BigInt BigInt::operator-() const
331
7.45k
   {
332
7.45k
   BigInt x = (*this);
333
7.45k
   x.flip_sign();
334
7.45k
   return x;
335
7.45k
   }
336
337
size_t BigInt::reduce_below(const BigInt& p, secure_vector<word>& ws)
338
59.1M
   {
339
59.1M
   if(p.is_negative() || this->is_negative())
340
0
      throw Invalid_Argument("BigInt::reduce_below both values must be positive");
341
59.1M
342
59.1M
   const size_t p_words = p.sig_words();
343
59.1M
344
59.1M
   if(size() < p_words + 1)
345
538
      grow_to(p_words + 1);
346
59.1M
347
59.1M
   if(ws.size() < p_words + 1)
348
2.63M
      ws.resize(p_words + 1);
349
59.1M
350
59.1M
   clear_mem(ws.data(), ws.size());
351
59.1M
352
59.1M
   size_t reductions = 0;
353
59.1M
354
59.1M
   for(;;)
355
150M
      {
356
150M
      word borrow = bigint_sub3(ws.data(), data(), p_words + 1, p.data(), p_words);
357
150M
      if(borrow)
358
59.1M
         break;
359
91.7M
360
91.7M
      ++reductions;
361
91.7M
      swap_reg(ws);
362
91.7M
      }
363
59.1M
364
59.1M
   return reductions;
365
59.1M
   }
366
367
void BigInt::ct_reduce_below(const BigInt& mod, secure_vector<word>& ws, size_t bound)
368
6.96M
   {
369
6.96M
   if(mod.is_negative() || this->is_negative())
370
0
      throw Invalid_Argument("BigInt::ct_reduce_below both values must be positive");
371
6.96M
372
6.96M
   const size_t mod_words = mod.sig_words();
373
6.96M
374
6.96M
   grow_to(mod_words);
375
6.96M
376
6.96M
   const size_t sz = size();
377
6.96M
378
6.96M
   ws.resize(sz);
379
6.96M
380
6.96M
   clear_mem(ws.data(), sz);
381
6.96M
382
20.8M
   for(size_t i = 0; i != bound; ++i)
383
13.9M
      {
384
13.9M
      word borrow = bigint_sub3(ws.data(), data(), sz, mod.data(), mod_words);
385
13.9M
386
13.9M
      CT::Mask<word>::is_zero(borrow).select_n(mutable_data(), ws.data(), data(), sz);
387
13.9M
      }
388
6.96M
   }
389
390
/*
391
* Return the absolute value of this number
392
*/
393
BigInt BigInt::abs() const
394
1.27k
   {
395
1.27k
   BigInt x = (*this);
396
1.27k
   x.set_sign(Positive);
397
1.27k
   return x;
398
1.27k
   }
399
400
void BigInt::binary_encode(uint8_t buf[]) const
401
50.0k
   {
402
50.0k
   this->binary_encode(buf, bytes());
403
50.0k
   }
404
405
/*
406
* Encode this number into bytes
407
*/
408
void BigInt::binary_encode(uint8_t output[], size_t len) const
409
110k
   {
410
110k
   const size_t full_words = len / sizeof(word);
411
110k
   const size_t extra_bytes = len % sizeof(word);
412
110k
413
1.30M
   for(size_t i = 0; i != full_words; ++i)
414
1.19M
      {
415
1.19M
      const word w = word_at(i);
416
1.19M
      store_be(w, output + (len - (i+1)*sizeof(word)));
417
1.19M
      }
418
110k
419
110k
   if(extra_bytes > 0)
420
61.9k
      {
421
61.9k
      const word w = word_at(full_words);
422
61.9k
423
208k
      for(size_t i = 0; i != extra_bytes; ++i)
424
146k
         {
425
146k
         output[extra_bytes - i - 1] = get_byte(sizeof(word) - i - 1, w);
426
146k
         }
427
61.9k
      }
428
110k
   }
429
430
/*
431
* Set this number to the value in buf
432
*/
433
void BigInt::binary_decode(const uint8_t buf[], size_t length)
434
622k
   {
435
622k
   clear();
436
622k
437
622k
   const size_t full_words = length / sizeof(word);
438
622k
   const size_t extra_bytes = length % sizeof(word);
439
622k
440
322k
   secure_vector<word> reg((round_up(full_words + (extra_bytes > 0 ? 1 : 0), 8)));
441
622k
442
4.71M
   for(size_t i = 0; i != full_words; ++i)
443
4.09M
      {
444
4.09M
      reg[i] = load_be<word>(buf + length - sizeof(word)*(i+1), 0);
445
4.09M
      }
446
622k
447
622k
   if(extra_bytes > 0)
448
300k
      {
449
813k
      for(size_t i = 0; i != extra_bytes; ++i)
450
513k
         reg[full_words] = (reg[full_words] << 8) | buf[i];
451
300k
      }
452
622k
453
622k
   m_data.swap(reg);
454
622k
   }
455
456
void BigInt::ct_cond_add(bool predicate, const BigInt& value)
457
777k
   {
458
777k
   if(this->is_negative() || value.is_negative())
459
0
      throw Invalid_Argument("BigInt::ct_cond_add requires both values to be positive");
460
777k
   this->grow_to(1 + value.sig_words());
461
777k
462
777k
   bigint_cnd_add(static_cast<word>(predicate),
463
777k
                  this->mutable_data(), this->size(),
464
777k
                  value.data(), value.sig_words());
465
777k
   }
466
467
void BigInt::ct_cond_swap(bool predicate, BigInt& other)
468
157M
   {
469
157M
   const size_t max_words = std::max(size(), other.size());
470
157M
   grow_to(max_words);
471
157M
   other.grow_to(max_words);
472
157M
473
157M
   bigint_cnd_swap(predicate, this->mutable_data(), other.mutable_data(), max_words);
474
157M
   }
475
476
void BigInt::cond_flip_sign(bool predicate)
477
19.7M
   {
478
   // This code is assuming Negative == 0, Positive == 1
479
19.7M
480
19.7M
   const auto mask = CT::Mask<uint8_t>::expand(predicate);
481
19.7M
482
19.7M
   const uint8_t current_sign = static_cast<uint8_t>(sign());
483
19.7M
484
19.7M
   const uint8_t new_sign = mask.select(current_sign ^ 1, current_sign);
485
19.7M
486
19.7M
   set_sign(static_cast<Sign>(new_sign));
487
19.7M
   }
488
489
void BigInt::ct_cond_assign(bool predicate, const BigInt& other)
490
1.51M
   {
491
1.51M
   const size_t t_words = size();
492
1.51M
   const size_t o_words = other.size();
493
1.51M
494
1.51M
   if(o_words < t_words)
495
30.0k
      grow_to(o_words);
496
1.51M
497
1.51M
   const size_t r_words = std::max(t_words, o_words);
498
1.51M
499
1.51M
   const auto mask = CT::Mask<word>::expand(predicate);
500
1.51M
501
38.2M
   for(size_t i = 0; i != r_words; ++i)
502
36.6M
      {
503
36.6M
      const word o_word = other.word_at(i);
504
36.6M
      const word t_word = this->word_at(i);
505
36.6M
      this->set_word_at(i, mask.select(o_word, t_word));
506
36.6M
      }
507
1.51M
508
1.51M
   const bool different_sign = sign() != other.sign();
509
1.51M
   cond_flip_sign(predicate && different_sign);
510
1.51M
   }
511
512
#if defined(BOTAN_HAS_VALGRIND)
513
void BigInt::const_time_poison() const
514
   {
515
   CT::poison(m_data.const_data(), m_data.size());
516
   }
517
518
void BigInt::const_time_unpoison() const
519
   {
520
   CT::unpoison(m_data.const_data(), m_data.size());
521
   }
522
#endif
523
524
void BigInt::const_time_lookup(secure_vector<word>& output,
525
                               const std::vector<BigInt>& vec,
526
                               size_t idx)
527
0
   {
528
0
   const size_t words = output.size();
529
0
530
0
   clear_mem(output.data(), output.size());
531
0
532
0
   CT::poison(&idx, sizeof(idx));
533
0
534
0
   for(size_t i = 0; i != vec.size(); ++i)
535
0
      {
536
0
      BOTAN_ASSERT(vec[i].size() >= words,
537
0
                   "Word size as expected in const_time_lookup");
538
0
539
0
      const auto mask = CT::Mask<word>::is_equal(i, idx);
540
0
541
0
      for(size_t w = 0; w != words; ++w)
542
0
         {
543
0
         const word viw = vec[i].word_at(w);
544
0
         output[w] = mask.if_set_return(viw);
545
0
         }
546
0
      }
547
0
548
0
   CT::unpoison(idx);
549
0
   CT::unpoison(output.data(), output.size());
550
0
   }
551
552
}