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

randombit / botan / 5123321399

30 May 2023 04:06PM UTC coverage: 92.213% (+0.004%) from 92.209%
5123321399

Pull #3558

github

web-flow
Merge dd72f7389 into 057bcbc35
Pull Request #3558: Add braces around all if/else statements

75602 of 81986 relevant lines covered (92.21%)

11859779.3 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,045✔
19
#if BOTAN_MP_WORD_BITS == 64
20
   m_data.set_word_at(0, n);
230,045✔
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,045✔
26

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

31
#if BOTAN_MP_WORD_BITS == 64
32
   bn.set_word_at(0, n);
25,341✔
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,341✔
39
}
×
40

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

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

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

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

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

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

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

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

91
BigInt::BigInt(const uint8_t input[], size_t length) { binary_decode(input, length); }
207,676✔
92

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

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

102
   BigInt bn;
21,273✔
103
   bn.binary_decode(input, length);
21,273✔
104

105
   if(input_bits > max_bits) {
21,273✔
106
      const size_t bits_to_shift = input_bits - max_bits;
8,941✔
107

108
      bn >>= bits_to_shift;
8,941✔
109
   }
110

111
   return bn;
21,273✔
112
}
×
113

114
/*
115
* Construct a BigInt from an encoded BigInt
116
*/
117
BigInt::BigInt(RandomNumberGenerator& rng, size_t bits, bool set_high_bit) { randomize(rng, bits, set_high_bit); }
21,573✔
118

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

123
int32_t BigInt::cmp_word(word other) const {
4,010,899✔
124
   if(is_negative()) {
4,010,899✔
125
      return -1;  // other is positive ...
126
   }
127

128
   const size_t sw = this->sig_words();
3,977,680✔
129
   if(sw > 1) {
3,977,680✔
130
      return 1;  // must be larger since other is just one word ...
131
   }
132

133
   return bigint_cmp(this->data(), sw, &other, 1);
1,846,799✔
134
}
135

136
/*
137
* Comparison Function
138
*/
139
int32_t BigInt::cmp(const BigInt& other, bool check_signs) const {
532,958✔
140
   if(check_signs) {
532,958✔
141
      if(other.is_positive() && this->is_negative()) {
532,831✔
142
         return -1;
143
      }
144

145
      if(other.is_negative() && this->is_positive()) {
532,765✔
146
         return 1;
147
      }
148

149
      if(other.is_negative() && this->is_negative()) {
532,703✔
150
         return (-bigint_cmp(this->data(), this->size(), other.data(), other.size()));
66✔
151
      }
152
   }
153

154
   return bigint_cmp(this->data(), this->size(), other.data(), other.size());
532,764✔
155
}
156

157
bool BigInt::is_equal(const BigInt& other) const {
390,346✔
158
   if(this->sign() != other.sign()) {
390,346✔
159
      return false;
160
   }
161

162
   return bigint_ct_is_eq(this->data(), this->sig_words(), other.data(), other.sig_words()).is_set();
583,717✔
163
}
164

165
bool BigInt::is_less_than(const BigInt& other) const {
2,758,155✔
166
   if(this->is_negative() && other.is_positive()) {
2,758,155✔
167
      return true;
168
   }
169

170
   if(this->is_positive() && other.is_negative()) {
2,758,090✔
171
      return false;
172
   }
173

174
   if(other.is_negative() && this->is_negative()) {
2,758,028✔
175
      return bigint_ct_is_lt(other.data(), other.sig_words(), this->data(), this->sig_words()).is_set();
65✔
176
   }
177

178
   return bigint_ct_is_lt(this->data(), this->sig_words(), other.data(), other.sig_words()).is_set();
5,273,354✔
179
}
180

181
void BigInt::encode_words(word out[], size_t size) const {
1,958,298✔
182
   const size_t words = sig_words();
1,958,298✔
183

184
   if(words > size) {
1,958,298✔
185
      throw Encoding_Error("BigInt::encode_words value too large to encode");
×
186
   }
187

188
   clear_mem(out, size);
1,958,298✔
189
   copy_mem(out, data(), words);
1,958,298✔
190
}
1,958,298✔
191

192
size_t BigInt::Data::calc_sig_words() const {
108,541,127✔
193
   const size_t sz = m_reg.size();
108,541,127✔
194
   size_t sig = sz;
108,541,127✔
195

196
   word sub = 1;
108,541,127✔
197

198
   for(size_t i = 0; i != sz; ++i) {
1,858,365,985✔
199
      const word w = m_reg[sz - i - 1];
1,749,824,858✔
200
      sub &= ct_is_zero(w);
1,749,824,858✔
201
      sig -= sub;
1,749,824,858✔
202
   }
203

204
   /*
205
   * This depends on the data so is poisoned, but unpoison it here as
206
   * later conditionals are made on the size.
207
   */
208
   CT::unpoison(sig);
108,541,127✔
209

210
   return sig;
108,541,127✔
211
}
212

213
/*
214
* Return bits {offset...offset+length}
215
*/
216
uint32_t BigInt::get_substring(size_t offset, size_t length) const {
16,404,586✔
217
   if(length == 0 || length > 32) {
16,404,586✔
218
      throw Invalid_Argument("BigInt::get_substring invalid substring length");
×
219
   }
220

221
   const uint32_t mask = 0xFFFFFFFF >> (32 - length);
16,404,586✔
222

223
   const size_t word_offset = offset / BOTAN_MP_WORD_BITS;
16,404,586✔
224
   const size_t wshift = (offset % BOTAN_MP_WORD_BITS);
16,404,586✔
225

226
   /*
227
   * The substring is contained within one or at most two words. The
228
   * offset and length are not secret, so we can perform conditional
229
   * operations on those values.
230
   */
231
   const word w0 = word_at(word_offset);
16,404,586✔
232

233
   if(wshift == 0 || (offset + length) / BOTAN_MP_WORD_BITS == word_offset) {
16,404,586✔
234
      return static_cast<uint32_t>(w0 >> wshift) & mask;
15,633,527✔
235
   } else {
236
      const word w1 = word_at(word_offset + 1);
771,059✔
237
      return static_cast<uint32_t>((w0 >> wshift) | (w1 << (BOTAN_MP_WORD_BITS - wshift))) & mask;
771,059✔
238
   }
239
}
240

241
/*
242
* Convert this number to a uint32_t, if possible
243
*/
244
uint32_t BigInt::to_u32bit() const {
34,948✔
245
   if(is_negative()) {
34,948✔
246
      throw Encoding_Error("BigInt::to_u32bit: Number is negative");
×
247
   }
248
   if(bits() > 32) {
34,948✔
249
      throw Encoding_Error("BigInt::to_u32bit: Number is too big to convert");
15✔
250
   }
251

252
   uint32_t out = 0;
253
   for(size_t i = 0; i != 4; ++i) {
174,665✔
254
      out = (out << 8) | byte_at(3 - i);
139,732✔
255
   }
256
   return out;
34,933✔
257
}
258

259
/*
260
* Clear bit number n
261
*/
262
void BigInt::clear_bit(size_t n) {
19✔
263
   const size_t which = n / BOTAN_MP_WORD_BITS;
19✔
264

265
   if(which < size()) {
19✔
266
      const word mask = ~(static_cast<word>(1) << (n % BOTAN_MP_WORD_BITS));
19✔
267
      m_data.set_word_at(which, word_at(which) & mask);
19✔
268
   }
269
}
19✔
270

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

273
size_t BigInt::top_bits_free() const {
4,392,866✔
274
   const size_t words = sig_words();
4,392,866✔
275

276
   const word top_word = word_at(words - 1);
35,142,928✔
277
   const size_t bits_used = high_bit(top_word);
4,392,866✔
278
   CT::unpoison(bits_used);
4,392,866✔
279
   return BOTAN_MP_WORD_BITS - bits_used;
4,392,866✔
280
}
281

282
size_t BigInt::bits() const {
2,017,961✔
283
   const size_t words = sig_words();
2,017,961✔
284

285
   if(words == 0) {
2,017,961✔
286
      return 0;
287
   }
288

289
   const size_t full_words = (words - 1) * BOTAN_MP_WORD_BITS;
2,001,103✔
290
   const size_t top_bits = BOTAN_MP_WORD_BITS - top_bits_free();
2,001,103✔
291

292
   return full_words + top_bits;
2,001,103✔
293
}
294

295
/*
296
* Return the negation of this number
297
*/
298
BigInt BigInt::operator-() const {
2,901✔
299
   BigInt x = (*this);
2,901✔
300
   x.flip_sign();
2,901✔
301
   return x;
2,901✔
302
}
×
303

304
size_t BigInt::reduce_below(const BigInt& p, secure_vector<word>& ws) {
25,100,599✔
305
   if(p.is_negative() || this->is_negative()) {
25,100,599✔
306
      throw Invalid_Argument("BigInt::reduce_below both values must be positive");
×
307
   }
308

309
   const size_t p_words = p.sig_words();
25,100,599✔
310

311
   if(size() < p_words + 1) {
25,100,599✔
312
      grow_to(p_words + 1);
11,361✔
313
   }
314

315
   if(ws.size() < p_words + 1) {
25,100,599✔
316
      ws.resize(p_words + 1);
654,251✔
317
   }
318

319
   clear_mem(ws.data(), ws.size());
25,100,599✔
320

321
   size_t reductions = 0;
322

323
   for(;;) {
64,865,627✔
324
      word borrow = bigint_sub3(ws.data(), data(), p_words + 1, p.data(), p_words);
129,731,254✔
325
      if(borrow) {
64,865,627✔
326
         break;
327
      }
328

329
      ++reductions;
39,765,028✔
330
      swap_reg(ws);
64,865,627✔
331
   }
332

333
   return reductions;
25,100,599✔
334
}
335

336
void BigInt::ct_reduce_below(const BigInt& mod, secure_vector<word>& ws, size_t bound) {
8,380,975✔
337
   if(mod.is_negative() || this->is_negative()) {
8,380,975✔
338
      throw Invalid_Argument("BigInt::ct_reduce_below both values must be positive");
×
339
   }
340

341
   const size_t mod_words = mod.sig_words();
8,380,975✔
342

343
   grow_to(mod_words);
8,380,975✔
344

345
   const size_t sz = size();
8,380,975✔
346

347
   ws.resize(sz);
8,380,975✔
348

349
   clear_mem(ws.data(), sz);
8,380,975✔
350

351
   for(size_t i = 0; i != bound; ++i) {
25,142,925✔
352
      word borrow = bigint_sub3(ws.data(), data(), sz, mod.data(), mod_words);
16,761,950✔
353

354
      CT::Mask<word>::is_zero(borrow).select_n(mutable_data(), ws.data(), data(), sz);
33,523,900✔
355
   }
356
}
8,380,975✔
357

358
/*
359
* Return the absolute value of this number
360
*/
361
BigInt BigInt::abs() const {
1,028✔
362
   BigInt x = (*this);
1,028✔
363
   x.set_sign(Positive);
1,028✔
364
   return x;
1,028✔
365
}
366

367
void BigInt::binary_encode(uint8_t buf[]) const { this->binary_encode(buf, bytes()); }
73,245✔
368

369
/*
370
* Encode this number into bytes
371
*/
372
void BigInt::binary_encode(uint8_t output[], size_t len) const {
105,249✔
373
   const size_t full_words = len / sizeof(word);
105,249✔
374
   const size_t extra_bytes = len % sizeof(word);
105,249✔
375

376
   for(size_t i = 0; i != full_words; ++i) {
1,153,483✔
377
      const word w = word_at(i);
1,048,234✔
378
      store_be(w, output + (len - (i + 1) * sizeof(word)));
1,048,234✔
379
   }
380

381
   if(extra_bytes > 0) {
105,249✔
382
      const word w = word_at(full_words);
47,584✔
383

384
      for(size_t i = 0; i != extra_bytes; ++i) {
195,643✔
385
         output[extra_bytes - i - 1] = get_byte_var(sizeof(word) - i - 1, w);
148,059✔
386
      }
387
   }
388
}
105,249✔
389

390
/*
391
* Set this number to the value in buf
392
*/
393
void BigInt::binary_decode(const uint8_t buf[], size_t length) {
582,392✔
394
   clear();
582,392✔
395

396
   const size_t full_words = length / sizeof(word);
582,392✔
397
   const size_t extra_bytes = length % sizeof(word);
582,392✔
398

399
   secure_vector<word> reg((round_up(full_words + (extra_bytes > 0 ? 1 : 0), 8)));
1,307,450✔
400

401
   for(size_t i = 0; i != full_words; ++i) {
3,998,576✔
402
      reg[i] = load_be<word>(buf + length - sizeof(word) * (i + 1), 0);
3,416,184✔
403
   }
404

405
   if(extra_bytes > 0) {
582,392✔
406
      for(size_t i = 0; i != extra_bytes; ++i) {
1,381,988✔
407
         reg[full_words] = (reg[full_words] << 8) | buf[i];
1,012,180✔
408
      }
409
   }
410

411
   m_data.swap(reg);
582,392✔
412
}
582,392✔
413

414
void BigInt::ct_cond_add(bool predicate, const BigInt& value) {
7,932,737✔
415
   if(this->is_negative() || value.is_negative()) {
7,932,737✔
416
      throw Invalid_Argument("BigInt::ct_cond_add requires both values to be positive");
×
417
   }
418
   this->grow_to(1 + value.sig_words());
13,294,542✔
419

420
   bigint_cnd_add(static_cast<word>(predicate), this->mutable_data(), this->size(), value.data(), value.sig_words());
7,932,737✔
421
}
7,932,737✔
422

423
void BigInt::ct_cond_swap(bool predicate, BigInt& other) {
152,734,254✔
424
   const size_t max_words = std::max(size(), other.size());
152,734,254✔
425
   grow_to(max_words);
152,734,254✔
426
   other.grow_to(max_words);
152,734,254✔
427

428
   bigint_cnd_swap(predicate, this->mutable_data(), other.mutable_data(), max_words);
152,734,254✔
429
}
152,734,254✔
430

431
void BigInt::cond_flip_sign(bool predicate) {
22,098,487✔
432
   // This code is assuming Negative == 0, Positive == 1
433

434
   const auto mask = CT::Mask<uint8_t>::expand(predicate);
22,098,487✔
435

436
   const uint8_t current_sign = static_cast<uint8_t>(sign());
22,098,487✔
437

438
   const uint8_t new_sign = mask.select(current_sign ^ 1, current_sign);
22,098,487✔
439

440
   set_sign(static_cast<Sign>(new_sign));
22,098,487✔
441
}
22,098,487✔
442

443
void BigInt::ct_cond_assign(bool predicate, const BigInt& other) {
1,772,865✔
444
   const size_t t_words = size();
1,772,865✔
445
   const size_t o_words = other.size();
1,772,865✔
446

447
   if(o_words < t_words) {
1,772,865✔
448
      grow_to(o_words);
44,242✔
449
   }
450

451
   const size_t r_words = std::max(t_words, o_words);
1,772,865✔
452

453
   const auto mask = CT::Mask<word>::expand(predicate);
1,772,865✔
454

455
   for(size_t i = 0; i != r_words; ++i) {
28,436,036✔
456
      const word o_word = other.word_at(i);
26,663,171✔
457
      const word t_word = this->word_at(i);
26,663,171✔
458
      this->set_word_at(i, mask.select(o_word, t_word));
26,663,171✔
459
   }
460

461
   const bool different_sign = sign() != other.sign();
1,772,865✔
462
   cond_flip_sign(predicate && different_sign);
1,772,865✔
463
}
1,772,865✔
464

465
#if defined(BOTAN_HAS_VALGRIND)
466
void BigInt::const_time_poison() const { CT::poison(m_data.const_data(), m_data.size()); }
467

468
void BigInt::const_time_unpoison() const { CT::unpoison(m_data.const_data(), m_data.size()); }
469
#endif
470

471
}  // 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