• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

randombit / botan / 5111374265

29 May 2023 11:19AM UTC coverage: 92.227% (+0.5%) from 91.723%
5111374265

push

github

randombit
Next release will be 3.1.0. Update release notes

75588 of 81959 relevant lines covered (92.23%)

11886470.91 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

94.88
/src/lib/math/bigint/bigint.cpp
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

10
#include <botan/internal/bit_ops.h>
11
#include <botan/internal/ct_utils.h>
12
#include <botan/internal/loadstor.h>
13
#include <botan/internal/mp_core.h>
14
#include <botan/internal/rounding.h>
15

16
namespace Botan {
17

18
BigInt::BigInt(uint64_t n) {
230,025✔
19
#if BOTAN_MP_WORD_BITS == 64
20
   m_data.set_word_at(0, n);
230,025✔
21
#else
22
   m_data.set_word_at(1, static_cast<word>(n >> 32));
23
   m_data.set_word_at(0, static_cast<word>(n));
24
#endif
25
}
230,025✔
26

27
//static
28
BigInt BigInt::from_u64(uint64_t n) {
25,358✔
29
   BigInt bn;
25,358✔
30

31
#if BOTAN_MP_WORD_BITS == 64
32
   bn.set_word_at(0, n);
25,358✔
33
#else
34
   bn.set_word_at(1, static_cast<word>(n >> 32));
35
   bn.set_word_at(0, static_cast<word>(n));
36
#endif
37

38
   return bn;
25,358✔
39
}
×
40

41
//static
42
BigInt BigInt::from_word(word n) {
572,098✔
43
   BigInt bn;
572,098✔
44
   bn.set_word_at(0, n);
572,098✔
45
   return bn;
572,098✔
46
}
×
47

48
//static
49
BigInt BigInt::from_s32(int32_t n) {
2,655✔
50
   if(n >= 0)
2,655✔
51
      return BigInt::from_u64(static_cast<uint64_t>(n));
2✔
52
   else
53
      return -BigInt::from_u64(static_cast<uint64_t>(-n));
5,306✔
54
}
55

56
//static
57
BigInt BigInt::with_capacity(size_t size) {
13,057,972✔
58
   BigInt bn;
13,057,972✔
59
   bn.grow_to(size);
13,057,972✔
60
   return bn;
13,057,972✔
61
}
×
62

63
/*
64
* Construct a BigInt from a string
65
*/
66
BigInt::BigInt(std::string_view str) {
44,410✔
67
   Base base = Decimal;
44,410✔
68
   size_t markers = 0;
44,410✔
69
   bool negative = false;
44,410✔
70

71
   if(str.length() > 0 && str[0] == '-') {
44,410✔
72
      markers += 1;
73
      negative = true;
74
   }
75

76
   if(str.length() > markers + 2 && str[markers] == '0' && str[markers + 1] == 'x') {
44,410✔
77
      markers += 2;
78
      base = Hexadecimal;
79
   }
80

81
   *this = decode(cast_char_ptr_to_uint8(str.data()) + markers, str.length() - markers, base);
44,410✔
82

83
   if(negative)
44,410✔
84
      set_sign(Negative);
445✔
85
   else
86
      set_sign(Positive);
43,965✔
87
}
44,410✔
88

89
BigInt::BigInt(const uint8_t input[], size_t length) { binary_decode(input, length); }
207,746✔
90

91
/*
92
* Construct a BigInt from an encoded BigInt
93
*/
94
BigInt::BigInt(const uint8_t input[], size_t length, Base base) { *this = decode(input, length, base); }
4✔
95

96
//static
97
BigInt BigInt::from_bytes_with_max_bits(const uint8_t input[], size_t length, size_t max_bits) {
21,288✔
98
   const size_t input_bits = 8 * length;
21,288✔
99

100
   BigInt bn;
21,288✔
101
   bn.binary_decode(input, length);
21,288✔
102

103
   if(input_bits > max_bits) {
21,288✔
104
      const size_t bits_to_shift = input_bits - max_bits;
8,949✔
105

106
      bn >>= bits_to_shift;
8,949✔
107
   }
108

109
   return bn;
21,288✔
110
}
×
111

112
/*
113
* Construct a BigInt from an encoded BigInt
114
*/
115
BigInt::BigInt(RandomNumberGenerator& rng, size_t bits, bool set_high_bit) { randomize(rng, bits, set_high_bit); }
22,367✔
116

117
uint8_t BigInt::byte_at(size_t n) const {
286,350✔
118
   return get_byte_var(sizeof(word) - (n % sizeof(word)) - 1, word_at(n / sizeof(word)));
286,350✔
119
}
120

121
int32_t BigInt::cmp_word(word other) const {
4,018,367✔
122
   if(is_negative())
4,018,367✔
123
      return -1;  // other is positive ...
124

125
   const size_t sw = this->sig_words();
3,985,187✔
126
   if(sw > 1)
3,985,187✔
127
      return 1;  // must be larger since other is just one word ...
128

129
   return bigint_cmp(this->data(), sw, &other, 1);
1,845,168✔
130
}
131

132
/*
133
* Comparison Function
134
*/
135
int32_t BigInt::cmp(const BigInt& other, bool check_signs) const {
537,105✔
136
   if(check_signs) {
537,105✔
137
      if(other.is_positive() && this->is_negative())
536,978✔
138
         return -1;
139

140
      if(other.is_negative() && this->is_positive())
536,902✔
141
         return 1;
142

143
      if(other.is_negative() && this->is_negative())
536,856✔
144
         return (-bigint_cmp(this->data(), this->size(), other.data(), other.size()));
64✔
145
   }
146

147
   return bigint_cmp(this->data(), this->size(), other.data(), other.size());
536,919✔
148
}
149

150
bool BigInt::is_equal(const BigInt& other) const {
391,481✔
151
   if(this->sign() != other.sign())
391,481✔
152
      return false;
153

154
   return bigint_ct_is_eq(this->data(), this->sig_words(), other.data(), other.sig_words()).is_set();
585,091✔
155
}
156

157
bool BigInt::is_less_than(const BigInt& other) const {
2,756,057✔
158
   if(this->is_negative() && other.is_positive())
2,756,057✔
159
      return true;
160

161
   if(this->is_positive() && other.is_negative())
2,755,995✔
162
      return false;
163

164
   if(other.is_negative() && this->is_negative()) {
2,755,936✔
165
      return bigint_ct_is_lt(other.data(), other.sig_words(), this->data(), this->sig_words()).is_set();
63✔
166
   }
167

168
   return bigint_ct_is_lt(this->data(), this->sig_words(), other.data(), other.sig_words()).is_set();
5,269,763✔
169
}
170

171
void BigInt::encode_words(word out[], size_t size) const {
1,957,818✔
172
   const size_t words = sig_words();
1,957,818✔
173

174
   if(words > size)
1,957,818✔
175
      throw Encoding_Error("BigInt::encode_words value too large to encode");
×
176

177
   clear_mem(out, size);
1,957,818✔
178
   copy_mem(out, data(), words);
1,957,818✔
179
}
1,957,818✔
180

181
size_t BigInt::Data::calc_sig_words() const {
108,248,676✔
182
   const size_t sz = m_reg.size();
108,248,676✔
183
   size_t sig = sz;
108,248,676✔
184

185
   word sub = 1;
108,248,676✔
186

187
   for(size_t i = 0; i != sz; ++i) {
1,850,144,108✔
188
      const word w = m_reg[sz - i - 1];
1,741,895,432✔
189
      sub &= ct_is_zero(w);
1,741,895,432✔
190
      sig -= sub;
1,741,895,432✔
191
   }
192

193
   /*
194
   * This depends on the data so is poisoned, but unpoison it here as
195
   * later conditionals are made on the size.
196
   */
197
   CT::unpoison(sig);
108,248,676✔
198

199
   return sig;
108,248,676✔
200
}
201

202
/*
203
* Return bits {offset...offset+length}
204
*/
205
uint32_t BigInt::get_substring(size_t offset, size_t length) const {
16,588,117✔
206
   if(length == 0 || length > 32)
16,588,117✔
207
      throw Invalid_Argument("BigInt::get_substring invalid substring length");
×
208

209
   const uint32_t mask = 0xFFFFFFFF >> (32 - length);
16,588,117✔
210

211
   const size_t word_offset = offset / BOTAN_MP_WORD_BITS;
16,588,117✔
212
   const size_t wshift = (offset % BOTAN_MP_WORD_BITS);
16,588,117✔
213

214
   /*
215
   * The substring is contained within one or at most two words. The
216
   * offset and length are not secret, so we can perform conditional
217
   * operations on those values.
218
   */
219
   const word w0 = word_at(word_offset);
16,588,117✔
220

221
   if(wshift == 0 || (offset + length) / BOTAN_MP_WORD_BITS == word_offset) {
16,588,117✔
222
      return static_cast<uint32_t>(w0 >> wshift) & mask;
15,805,493✔
223
   } else {
224
      const word w1 = word_at(word_offset + 1);
782,624✔
225
      return static_cast<uint32_t>((w0 >> wshift) | (w1 << (BOTAN_MP_WORD_BITS - wshift))) & mask;
782,624✔
226
   }
227
}
228

229
/*
230
* Convert this number to a uint32_t, if possible
231
*/
232
uint32_t BigInt::to_u32bit() const {
34,948✔
233
   if(is_negative())
34,948✔
234
      throw Encoding_Error("BigInt::to_u32bit: Number is negative");
×
235
   if(bits() > 32)
34,948✔
236
      throw Encoding_Error("BigInt::to_u32bit: Number is too big to convert");
15✔
237

238
   uint32_t out = 0;
239
   for(size_t i = 0; i != 4; ++i)
174,665✔
240
      out = (out << 8) | byte_at(3 - i);
139,732✔
241
   return out;
34,933✔
242
}
243

244
/*
245
* Clear bit number n
246
*/
247
void BigInt::clear_bit(size_t n) {
20✔
248
   const size_t which = n / BOTAN_MP_WORD_BITS;
20✔
249

250
   if(which < size()) {
20✔
251
      const word mask = ~(static_cast<word>(1) << (n % BOTAN_MP_WORD_BITS));
20✔
252
      m_data.set_word_at(which, word_at(which) & mask);
20✔
253
   }
254
}
20✔
255

256
size_t BigInt::bytes() const { return round_up(bits(), 8) / 8; }
213,442✔
257

258
size_t BigInt::top_bits_free() const {
4,392,512✔
259
   const size_t words = sig_words();
4,392,512✔
260

261
   const word top_word = word_at(words - 1);
35,140,096✔
262
   const size_t bits_used = high_bit(top_word);
4,392,512✔
263
   CT::unpoison(bits_used);
4,392,512✔
264
   return BOTAN_MP_WORD_BITS - bits_used;
4,392,512✔
265
}
266

267
size_t BigInt::bits() const {
2,023,192✔
268
   const size_t words = sig_words();
2,023,192✔
269

270
   if(words == 0)
2,023,192✔
271
      return 0;
272

273
   const size_t full_words = (words - 1) * BOTAN_MP_WORD_BITS;
2,006,326✔
274
   const size_t top_bits = BOTAN_MP_WORD_BITS - top_bits_free();
2,006,326✔
275

276
   return full_words + top_bits;
2,006,326✔
277
}
278

279
/*
280
* Return the negation of this number
281
*/
282
BigInt BigInt::operator-() const {
2,877✔
283
   BigInt x = (*this);
2,877✔
284
   x.flip_sign();
2,877✔
285
   return x;
2,877✔
286
}
×
287

288
size_t BigInt::reduce_below(const BigInt& p, secure_vector<word>& ws) {
25,085,352✔
289
   if(p.is_negative() || this->is_negative())
25,085,352✔
290
      throw Invalid_Argument("BigInt::reduce_below both values must be positive");
×
291

292
   const size_t p_words = p.sig_words();
25,085,352✔
293

294
   if(size() < p_words + 1)
25,085,352✔
295
      grow_to(p_words + 1);
11,117✔
296

297
   if(ws.size() < p_words + 1)
25,085,352✔
298
      ws.resize(p_words + 1);
652,392✔
299

300
   clear_mem(ws.data(), ws.size());
25,085,352✔
301

302
   size_t reductions = 0;
303

304
   for(;;) {
64,827,419✔
305
      word borrow = bigint_sub3(ws.data(), data(), p_words + 1, p.data(), p_words);
129,654,838✔
306
      if(borrow)
64,827,419✔
307
         break;
308

309
      ++reductions;
39,742,067✔
310
      swap_reg(ws);
64,827,419✔
311
   }
312

313
   return reductions;
25,085,352✔
314
}
315

316
void BigInt::ct_reduce_below(const BigInt& mod, secure_vector<word>& ws, size_t bound) {
8,337,499✔
317
   if(mod.is_negative() || this->is_negative())
8,337,499✔
318
      throw Invalid_Argument("BigInt::ct_reduce_below both values must be positive");
×
319

320
   const size_t mod_words = mod.sig_words();
8,337,499✔
321

322
   grow_to(mod_words);
8,337,499✔
323

324
   const size_t sz = size();
8,337,499✔
325

326
   ws.resize(sz);
8,337,499✔
327

328
   clear_mem(ws.data(), sz);
8,337,499✔
329

330
   for(size_t i = 0; i != bound; ++i) {
25,012,497✔
331
      word borrow = bigint_sub3(ws.data(), data(), sz, mod.data(), mod_words);
16,674,998✔
332

333
      CT::Mask<word>::is_zero(borrow).select_n(mutable_data(), ws.data(), data(), sz);
33,349,996✔
334
   }
335
}
8,337,499✔
336

337
/*
338
* Return the absolute value of this number
339
*/
340
BigInt BigInt::abs() const {
958✔
341
   BigInt x = (*this);
958✔
342
   x.set_sign(Positive);
958✔
343
   return x;
958✔
344
}
345

346
void BigInt::binary_encode(uint8_t buf[]) const { this->binary_encode(buf, bytes()); }
73,315✔
347

348
/*
349
* Encode this number into bytes
350
*/
351
void BigInt::binary_encode(uint8_t output[], size_t len) const {
105,352✔
352
   const size_t full_words = len / sizeof(word);
105,352✔
353
   const size_t extra_bytes = len % sizeof(word);
105,352✔
354

355
   for(size_t i = 0; i != full_words; ++i) {
1,154,142✔
356
      const word w = word_at(i);
1,048,790✔
357
      store_be(w, output + (len - (i + 1) * sizeof(word)));
1,048,790✔
358
   }
359

360
   if(extra_bytes > 0) {
105,352✔
361
      const word w = word_at(full_words);
47,623✔
362

363
      for(size_t i = 0; i != extra_bytes; ++i) {
195,816✔
364
         output[extra_bytes - i - 1] = get_byte_var(sizeof(word) - i - 1, w);
148,193✔
365
      }
366
   }
367
}
105,352✔
368

369
/*
370
* Set this number to the value in buf
371
*/
372
void BigInt::binary_decode(const uint8_t buf[], size_t length) {
585,383✔
373
   clear();
585,383✔
374

375
   const size_t full_words = length / sizeof(word);
585,383✔
376
   const size_t extra_bytes = length % sizeof(word);
585,383✔
377

378
   secure_vector<word> reg((round_up(full_words + (extra_bytes > 0 ? 1 : 0), 8)));
1,314,087✔
379

380
   for(size_t i = 0; i != full_words; ++i) {
4,052,804✔
381
      reg[i] = load_be<word>(buf + length - sizeof(word) * (i + 1), 0);
3,467,421✔
382
   }
383

384
   if(extra_bytes > 0) {
585,383✔
385
      for(size_t i = 0; i != extra_bytes; ++i)
1,378,057✔
386
         reg[full_words] = (reg[full_words] << 8) | buf[i];
1,009,423✔
387
   }
388

389
   m_data.swap(reg);
585,383✔
390
}
585,383✔
391

392
void BigInt::ct_cond_add(bool predicate, const BigInt& value) {
7,914,509✔
393
   if(this->is_negative() || value.is_negative())
7,914,509✔
394
      throw Invalid_Argument("BigInt::ct_cond_add requires both values to be positive");
×
395
   this->grow_to(1 + value.sig_words());
13,276,500✔
396

397
   bigint_cnd_add(static_cast<word>(predicate), this->mutable_data(), this->size(), value.data(), value.sig_words());
7,914,509✔
398
}
7,914,509✔
399

400
void BigInt::ct_cond_swap(bool predicate, BigInt& other) {
155,658,527✔
401
   const size_t max_words = std::max(size(), other.size());
155,658,527✔
402
   grow_to(max_words);
155,658,527✔
403
   other.grow_to(max_words);
155,658,527✔
404

405
   bigint_cnd_swap(predicate, this->mutable_data(), other.mutable_data(), max_words);
155,658,527✔
406
}
155,658,527✔
407

408
void BigInt::cond_flip_sign(bool predicate) {
21,983,896✔
409
   // This code is assuming Negative == 0, Positive == 1
410

411
   const auto mask = CT::Mask<uint8_t>::expand(predicate);
21,983,896✔
412

413
   const uint8_t current_sign = static_cast<uint8_t>(sign());
21,983,896✔
414

415
   const uint8_t new_sign = mask.select(current_sign ^ 1, current_sign);
21,983,896✔
416

417
   set_sign(static_cast<Sign>(new_sign));
21,983,896✔
418
}
21,983,896✔
419

420
void BigInt::ct_cond_assign(bool predicate, const BigInt& other) {
1,762,090✔
421
   const size_t t_words = size();
1,762,090✔
422
   const size_t o_words = other.size();
1,762,090✔
423

424
   if(o_words < t_words)
1,762,090✔
425
      grow_to(o_words);
44,214✔
426

427
   const size_t r_words = std::max(t_words, o_words);
1,762,090✔
428

429
   const auto mask = CT::Mask<word>::expand(predicate);
1,762,090✔
430

431
   for(size_t i = 0; i != r_words; ++i) {
28,080,443✔
432
      const word o_word = other.word_at(i);
26,318,353✔
433
      const word t_word = this->word_at(i);
26,318,353✔
434
      this->set_word_at(i, mask.select(o_word, t_word));
26,318,353✔
435
   }
436

437
   const bool different_sign = sign() != other.sign();
1,762,090✔
438
   cond_flip_sign(predicate && different_sign);
1,762,090✔
439
}
1,762,090✔
440

441
#if defined(BOTAN_HAS_VALGRIND)
442
void BigInt::const_time_poison() const { CT::poison(m_data.const_data(), m_data.size()); }
443

444
void BigInt::const_time_unpoison() const { CT::unpoison(m_data.const_data(), m_data.size()); }
445
#endif
446

447
}  // namespace Botan
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc