Coverage Report

Created: 2020-10-17 06:46

/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
92.5k
   {
19
92.5k
   m_data.set_words(words, length);
20
92.5k
   }
21
22
/*
23
* Construct a BigInt from a regular number
24
*/
25
BigInt::BigInt(uint64_t n)
26
5.57M
   {
27
5.57M
   if(n > 0)
28
2.73M
      {
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.73M
      m_data.set_word_at(0, n);
34
2.73M
#endif
35
2.73M
      }
36
5.57M
37
5.57M
   }
38
39
/*
40
* Construct a BigInt of the specified size
41
*/
42
BigInt::BigInt(Sign s, size_t size)
43
17.8M
   {
44
17.8M
   m_data.set_size(size);
45
17.8M
   m_signedness = s;
46
17.8M
   }
47
48
/*
49
* Construct a BigInt from a string
50
*/
51
BigInt::BigInt(const std::string& str)
52
18.5k
   {
53
18.5k
   Base base = Decimal;
54
18.5k
   size_t markers = 0;
55
18.5k
   bool negative = false;
56
18.5k
57
18.5k
   if(str.length() > 0 && str[0] == '-')
58
0
      {
59
0
      markers += 1;
60
0
      negative = true;
61
0
      }
62
18.5k
63
18.5k
   if(str.length() > markers + 2 && str[markers    ] == '0' &&
64
18.5k
                                    str[markers + 1] == 'x')
65
18.5k
      {
66
18.5k
      markers += 2;
67
18.5k
      base = Hexadecimal;
68
18.5k
      }
69
18.5k
70
18.5k
   *this = decode(cast_char_ptr_to_uint8(str.data()) + markers,
71
18.5k
                  str.length() - markers, base);
72
18.5k
73
18.5k
   if(negative) set_sign(Negative);
74
18.5k
   else         set_sign(Positive);
75
18.5k
   }
76
77
BigInt::BigInt(const uint8_t input[], size_t length)
78
107k
   {
79
107k
   binary_decode(input, length);
80
107k
   }
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
422
   {
92
422
   const size_t max_bytes = std::min(length, (max_bits + 7) / 8);
93
422
   binary_decode(buf, max_bytes);
94
422
95
422
   const size_t b = this->bits();
96
422
   if(b > max_bits)
97
0
      {
98
0
      *this >>= (b - max_bits);
99
0
      }
100
422
   }
101
102
/*
103
* Construct a BigInt from an encoded BigInt
104
*/
105
BigInt::BigInt(RandomNumberGenerator& rng, size_t bits, bool set_high_bit)
106
52.8k
   {
107
52.8k
   randomize(rng, bits, set_high_bit);
108
52.8k
   }
109
110
uint8_t BigInt::byte_at(size_t n) const
111
65.1k
   {
112
65.1k
   return get_byte(sizeof(word) - (n % sizeof(word)) - 1,
113
65.1k
                   word_at(n / sizeof(word)));
114
65.1k
   }
115
116
int32_t BigInt::cmp_word(word other) const
117
7.52M
   {
118
7.52M
   if(is_negative())
119
8.44k
      return -1; // other is positive ...
120
7.52M
121
7.52M
   const size_t sw = this->sig_words();
122
7.52M
   if(sw > 1)
123
6.88M
      return 1; // must be larger since other is just one word ...
124
640k
125
640k
   return bigint_cmp(this->data(), sw, &other, 1);
126
640k
   }
127
128
/*
129
* Comparison Function
130
*/
131
int32_t BigInt::cmp(const BigInt& other, bool check_signs) const
132
652k
   {
133
652k
   if(check_signs)
134
652k
      {
135
652k
      if(other.is_positive() && this->is_negative())
136
0
         return -1;
137
652k
138
652k
      if(other.is_negative() && this->is_positive())
139
1
         return 1;
140
652k
141
652k
      if(other.is_negative() && this->is_negative())
142
0
         return (-bigint_cmp(this->data(), this->size(),
143
0
                             other.data(), other.size()));
144
652k
      }
145
652k
146
652k
   return bigint_cmp(this->data(), this->size(),
147
652k
                     other.data(), other.size());
148
652k
   }
149
150
bool BigInt::is_equal(const BigInt& other) const
151
901k
   {
152
901k
   if(this->sign() != other.sign())
153
0
      return false;
154
901k
155
901k
   return bigint_ct_is_eq(this->data(), this->sig_words(),
156
901k
                          other.data(), other.sig_words()).is_set();
157
901k
   }
158
159
bool BigInt::is_less_than(const BigInt& other) const
160
5.65M
   {
161
5.65M
   if(this->is_negative() && other.is_positive())
162
109
      return true;
163
5.65M
164
5.65M
   if(this->is_positive() && other.is_negative())
165
0
      return false;
166
5.65M
167
5.65M
   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.65M
173
5.65M
   return bigint_ct_is_lt(this->data(), this->sig_words(),
174
5.65M
                          other.data(), other.sig_words()).is_set();
175
5.65M
   }
176
177
void BigInt::encode_words(word out[], size_t size) const
178
3.63M
   {
179
3.63M
   const size_t words = sig_words();
180
3.63M
181
3.63M
   if(words > size)
182
0
      throw Encoding_Error("BigInt::encode_words value too large to encode");
183
3.63M
184
3.63M
   clear_mem(out, size);
185
3.63M
   copy_mem(out, data(), words);
186
3.63M
   }
187
188
size_t BigInt::Data::calc_sig_words() const
189
146M
   {
190
146M
   const size_t sz = m_reg.size();
191
146M
   size_t sig = sz;
192
146M
193
146M
   word sub = 1;
194
146M
195
4.65G
   for(size_t i = 0; i != sz; ++i)
196
4.51G
      {
197
4.51G
      const word w = m_reg[sz - i - 1];
198
4.51G
      sub &= ct_is_zero(w);
199
4.51G
      sig -= sub;
200
4.51G
      }
201
146M
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
146M
   CT::unpoison(sig);
207
146M
208
146M
   return sig;
209
146M
   }
210
211
/*
212
* Return bits {offset...offset+length}
213
*/
214
uint32_t BigInt::get_substring(size_t offset, size_t length) const
215
15.9M
   {
216
15.9M
   if(length == 0 || length > 32)
217
0
      throw Invalid_Argument("BigInt::get_substring invalid substring length");
218
15.9M
219
15.9M
   const uint32_t mask = 0xFFFFFFFF >> (32 - length);
220
15.9M
221
15.9M
   const size_t word_offset = offset / BOTAN_MP_WORD_BITS;
222
15.9M
   const size_t wshift = (offset % BOTAN_MP_WORD_BITS);
223
15.9M
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
15.9M
   const word w0 = word_at(word_offset);
230
15.9M
231
15.9M
   if(wshift == 0 || (offset + length) / BOTAN_MP_WORD_BITS == word_offset)
232
15.0M
      {
233
15.0M
      return static_cast<uint32_t>(w0 >> wshift) & mask;
234
15.0M
      }
235
857k
   else
236
857k
      {
237
857k
      const word w1 = word_at(word_offset + 1);
238
857k
      return static_cast<uint32_t>((w0 >> wshift) | (w1 << (BOTAN_MP_WORD_BITS - wshift))) & mask;
239
857k
      }
240
15.9M
   }
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
317M
   {
263
317M
   const size_t which = n / BOTAN_MP_WORD_BITS;
264
317M
   const word mask = static_cast<word>(set_it) << (n % BOTAN_MP_WORD_BITS);
265
317M
   m_data.set_word_at(which, word_at(which) | mask);
266
317M
   }
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
198k
   {
284
198k
   return round_up(bits(), 8) / 8;
285
198k
   }
286
287
size_t BigInt::top_bits_free() const
288
11.1M
   {
289
11.1M
   const size_t words = sig_words();
290
11.1M
291
11.1M
   const word top_word = word_at(words - 1);
292
11.1M
   const size_t bits_used = high_bit(top_word);
293
11.1M
   CT::unpoison(bits_used);
294
11.1M
   return BOTAN_MP_WORD_BITS - bits_used;
295
11.1M
   }
296
297
size_t BigInt::bits() const
298
3.35M
   {
299
3.35M
   const size_t words = sig_words();
300
3.35M
301
3.35M
   if(words == 0)
302
12.6k
      return 0;
303
3.34M
304
3.34M
   const size_t full_words = (words - 1) * BOTAN_MP_WORD_BITS;
305
3.34M
   const size_t top_bits = BOTAN_MP_WORD_BITS - top_bits_free();
306
3.34M
307
3.34M
   return full_words + top_bits;
308
3.34M
   }
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.29k
   {
332
7.29k
   BigInt x = (*this);
333
7.29k
   x.flip_sign();
334
7.29k
   return x;
335
7.29k
   }
336
337
size_t BigInt::reduce_below(const BigInt& p, secure_vector<word>& ws)
338
58.9M
   {
339
58.9M
   if(p.is_negative() || this->is_negative())
340
0
      throw Invalid_Argument("BigInt::reduce_below both values must be positive");
341
58.9M
342
58.9M
   const size_t p_words = p.sig_words();
343
58.9M
344
58.9M
   if(size() < p_words + 1)
345
548
      grow_to(p_words + 1);
346
58.9M
347
58.9M
   if(ws.size() < p_words + 1)
348
2.60M
      ws.resize(p_words + 1);
349
58.9M
350
58.9M
   clear_mem(ws.data(), ws.size());
351
58.9M
352
58.9M
   size_t reductions = 0;
353
58.9M
354
58.9M
   for(;;)
355
150M
      {
356
150M
      word borrow = bigint_sub3(ws.data(), data(), p_words + 1, p.data(), p_words);
357
150M
      if(borrow)
358
58.9M
         break;
359
91.5M
360
91.5M
      ++reductions;
361
91.5M
      swap_reg(ws);
362
91.5M
      }
363
58.9M
364
58.9M
   return reductions;
365
58.9M
   }
366
367
void BigInt::ct_reduce_below(const BigInt& mod, secure_vector<word>& ws, size_t bound)
368
7.85M
   {
369
7.85M
   if(mod.is_negative() || this->is_negative())
370
0
      throw Invalid_Argument("BigInt::ct_reduce_below both values must be positive");
371
7.85M
372
7.85M
   const size_t mod_words = mod.sig_words();
373
7.85M
374
7.85M
   grow_to(mod_words);
375
7.85M
376
7.85M
   const size_t sz = size();
377
7.85M
378
7.85M
   ws.resize(sz);
379
7.85M
380
7.85M
   clear_mem(ws.data(), sz);
381
7.85M
382
23.5M
   for(size_t i = 0; i != bound; ++i)
383
15.7M
      {
384
15.7M
      word borrow = bigint_sub3(ws.data(), data(), sz, mod.data(), mod_words);
385
15.7M
386
15.7M
      CT::Mask<word>::is_zero(borrow).select_n(mutable_data(), ws.data(), data(), sz);
387
15.7M
      }
388
7.85M
   }
389
390
/*
391
* Return the absolute value of this number
392
*/
393
BigInt BigInt::abs() const
394
1.35k
   {
395
1.35k
   BigInt x = (*this);
396
1.35k
   x.set_sign(Positive);
397
1.35k
   return x;
398
1.35k
   }
399
400
void BigInt::binary_encode(uint8_t buf[]) const
401
50.6k
   {
402
50.6k
   this->binary_encode(buf, bytes());
403
50.6k
   }
404
405
/*
406
* Encode this number into bytes
407
*/
408
void BigInt::binary_encode(uint8_t output[], size_t len) const
409
111k
   {
410
111k
   const size_t full_words = len / sizeof(word);
411
111k
   const size_t extra_bytes = len % sizeof(word);
412
111k
413
1.31M
   for(size_t i = 0; i != full_words; ++i)
414
1.20M
      {
415
1.20M
      const word w = word_at(i);
416
1.20M
      store_be(w, output + (len - (i+1)*sizeof(word)));
417
1.20M
      }
418
111k
419
111k
   if(extra_bytes > 0)
420
62.1k
      {
421
62.1k
      const word w = word_at(full_words);
422
62.1k
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
62.1k
      }
428
111k
   }
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
628k
   {
435
628k
   clear();
436
628k
437
628k
   const size_t full_words = length / sizeof(word);
438
628k
   const size_t extra_bytes = length % sizeof(word);
439
628k
440
321k
   secure_vector<word> reg((round_up(full_words + (extra_bytes > 0 ? 1 : 0), 8)));
441
628k
442
5.02M
   for(size_t i = 0; i != full_words; ++i)
443
4.39M
      {
444
4.39M
      reg[i] = load_be<word>(buf + length - sizeof(word)*(i+1), 0);
445
4.39M
      }
446
628k
447
628k
   if(extra_bytes > 0)
448
307k
      {
449
852k
      for(size_t i = 0; i != extra_bytes; ++i)
450
545k
         reg[full_words] = (reg[full_words] << 8) | buf[i];
451
307k
      }
452
628k
453
628k
   m_data.swap(reg);
454
628k
   }
455
456
void BigInt::ct_cond_add(bool predicate, const BigInt& value)
457
941k
   {
458
941k
   if(this->is_negative() || value.is_negative())
459
0
      throw Invalid_Argument("BigInt::ct_cond_add requires both values to be positive");
460
941k
   this->grow_to(1 + value.sig_words());
461
941k
462
941k
   bigint_cnd_add(static_cast<word>(predicate),
463
941k
                  this->mutable_data(), this->size(),
464
941k
                  value.data(), value.sig_words());
465
941k
   }
466
467
void BigInt::ct_cond_swap(bool predicate, BigInt& other)
468
158M
   {
469
158M
   const size_t max_words = std::max(size(), other.size());
470
158M
   grow_to(max_words);
471
158M
   other.grow_to(max_words);
472
158M
473
158M
   bigint_cnd_swap(predicate, this->mutable_data(), other.mutable_data(), max_words);
474
158M
   }
475
476
void BigInt::cond_flip_sign(bool predicate)
477
21.8M
   {
478
   // This code is assuming Negative == 0, Positive == 1
479
21.8M
480
21.8M
   const auto mask = CT::Mask<uint8_t>::expand(predicate);
481
21.8M
482
21.8M
   const uint8_t current_sign = static_cast<uint8_t>(sign());
483
21.8M
484
21.8M
   const uint8_t new_sign = mask.select(current_sign ^ 1, current_sign);
485
21.8M
486
21.8M
   set_sign(static_cast<Sign>(new_sign));
487
21.8M
   }
488
489
void BigInt::ct_cond_assign(bool predicate, const BigInt& other)
490
1.60M
   {
491
1.60M
   const size_t t_words = size();
492
1.60M
   const size_t o_words = other.size();
493
1.60M
494
1.60M
   if(o_words < t_words)
495
29.0k
      grow_to(o_words);
496
1.60M
497
1.60M
   const size_t r_words = std::max(t_words, o_words);
498
1.60M
499
1.60M
   const auto mask = CT::Mask<word>::expand(predicate);
500
1.60M
501
42.4M
   for(size_t i = 0; i != r_words; ++i)
502
40.8M
      {
503
40.8M
      const word o_word = other.word_at(i);
504
40.8M
      const word t_word = this->word_at(i);
505
40.8M
      this->set_word_at(i, mask.select(o_word, t_word));
506
40.8M
      }
507
1.60M
508
1.60M
   const bool different_sign = sign() != other.sign();
509
1.60M
   cond_flip_sign(predicate && different_sign);
510
1.60M
   }
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
}