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

randombit / botan / 5079590438

25 May 2023 12:28PM UTC coverage: 92.228% (+0.5%) from 91.723%
5079590438

Pull #3502

github

Pull Request #3502: Apply clang-format to the codebase

75589 of 81959 relevant lines covered (92.23%)

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

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

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

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

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

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

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

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

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

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

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

89
BigInt::BigInt(const uint8_t input[], size_t length) { binary_decode(input, length); }
207,616✔
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,262✔
98
   const size_t input_bits = 8 * length;
21,262✔
99

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

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

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

109
   return bn;
21,262✔
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,526✔
116

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

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

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

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

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

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

143
      if(other.is_negative() && this->is_negative())
544,360✔
144
         return (-bigint_cmp(this->data(), this->size(), other.data(), other.size()));
78✔
145
   }
146

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

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

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

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

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

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

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

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

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

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

181
size_t BigInt::Data::calc_sig_words() const {
114,633,559✔
182
   const size_t sz = m_reg.size();
114,633,559✔
183
   size_t sig = sz;
114,633,559✔
184

185
   word sub = 1;
114,633,559✔
186

187
   for(size_t i = 0; i != sz; ++i) {
2,026,394,493✔
188
      const word w = m_reg[sz - i - 1];
1,911,760,934✔
189
      sub &= ct_is_zero(w);
1,911,760,934✔
190
      sig -= sub;
1,911,760,934✔
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);
114,633,559✔
198

199
   return sig;
114,633,559✔
200
}
201

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

209
   const uint32_t mask = 0xFFFFFFFF >> (32 - length);
17,652,098✔
210

211
   const size_t word_offset = offset / BOTAN_MP_WORD_BITS;
17,652,098✔
212
   const size_t wshift = (offset % BOTAN_MP_WORD_BITS);
17,652,098✔
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);
17,652,098✔
220

221
   if(wshift == 0 || (offset + length) / BOTAN_MP_WORD_BITS == word_offset) {
17,652,098✔
222
      return static_cast<uint32_t>(w0 >> wshift) & mask;
16,802,905✔
223
   } else {
224
      const word w1 = word_at(word_offset + 1);
849,193✔
225
      return static_cast<uint32_t>((w0 >> wshift) | (w1 << (BOTAN_MP_WORD_BITS - wshift))) & mask;
849,193✔
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) {
14✔
248
   const size_t which = n / BOTAN_MP_WORD_BITS;
14✔
249

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

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

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

261
   const word top_word = word_at(words - 1);
35,284,088✔
262
   const size_t bits_used = high_bit(top_word);
4,410,511✔
263
   CT::unpoison(bits_used);
4,410,511✔
264
   return BOTAN_MP_WORD_BITS - bits_used;
4,410,511✔
265
}
266

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

270
   if(words == 0)
2,038,208✔
271
      return 0;
272

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

276
   return full_words + top_bits;
2,021,250✔
277
}
278

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

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

292
   const size_t p_words = p.sig_words();
25,074,213✔
293

294
   if(size() < p_words + 1)
25,074,213✔
295
      grow_to(p_words + 1);
11,361✔
296

297
   if(ws.size() < p_words + 1)
25,074,213✔
298
      ws.resize(p_words + 1);
653,417✔
299

300
   clear_mem(ws.data(), ws.size());
25,074,213✔
301

302
   size_t reductions = 0;
303

304
   for(;;) {
64,817,788✔
305
      word borrow = bigint_sub3(ws.data(), data(), p_words + 1, p.data(), p_words);
129,635,576✔
306
      if(borrow)
64,817,788✔
307
         break;
308

309
      ++reductions;
39,743,575✔
310
      swap_reg(ws);
64,817,788✔
311
   }
312

313
   return reductions;
25,074,213✔
314
}
315

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

320
   const size_t mod_words = mod.sig_words();
9,203,191✔
321

322
   grow_to(mod_words);
9,203,191✔
323

324
   const size_t sz = size();
9,203,191✔
325

326
   ws.resize(sz);
9,203,191✔
327

328
   clear_mem(ws.data(), sz);
9,203,191✔
329

330
   for(size_t i = 0; i != bound; ++i) {
27,609,573✔
331
      word borrow = bigint_sub3(ws.data(), data(), sz, mod.data(), mod_words);
18,406,382✔
332

333
      CT::Mask<word>::is_zero(borrow).select_n(mutable_data(), ws.data(), data(), sz);
36,812,764✔
334
   }
335
}
9,203,191✔
336

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

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

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

355
   for(size_t i = 0; i != full_words; ++i) {
1,153,069✔
356
      const word w = word_at(i);
1,047,938✔
357
      store_be(w, output + (len - (i + 1) * sizeof(word)));
1,047,938✔
358
   }
359

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

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

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

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

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

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

384
   if(extra_bytes > 0) {
589,178✔
385
      for(size_t i = 0; i != extra_bytes; ++i)
1,382,106✔
386
         reg[full_words] = (reg[full_words] << 8) | buf[i];
1,012,285✔
387
   }
388

389
   m_data.swap(reg);
589,178✔
390
}
589,178✔
391

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

397
   bigint_cnd_add(static_cast<word>(predicate), this->mutable_data(), this->size(), value.data(), value.sig_words());
8,233,933✔
398
}
8,233,933✔
399

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

405
   bigint_cnd_swap(predicate, this->mutable_data(), other.mutable_data(), max_words);
162,224,497✔
406
}
162,224,497✔
407

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

411
   const auto mask = CT::Mask<uint8_t>::expand(predicate);
24,254,433✔
412

413
   const uint8_t current_sign = static_cast<uint8_t>(sign());
24,254,433✔
414

415
   const uint8_t new_sign = mask.select(current_sign ^ 1, current_sign);
24,254,433✔
416

417
   set_sign(static_cast<Sign>(new_sign));
24,254,433✔
418
}
24,254,433✔
419

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

424
   if(o_words < t_words)
1,974,278✔
425
      grow_to(o_words);
46,205✔
426

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

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

431
   for(size_t i = 0; i != r_words; ++i) {
34,447,261✔
432
      const word o_word = other.word_at(i);
32,472,983✔
433
      const word t_word = this->word_at(i);
32,472,983✔
434
      this->set_word_at(i, mask.select(o_word, t_word));
32,472,983✔
435
   }
436

437
   const bool different_sign = sign() != other.sign();
1,974,278✔
438
   cond_flip_sign(predicate && different_sign);
1,974,278✔
439
}
1,974,278✔
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
}
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