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

randombit / botan / 11087146043

28 Sep 2024 09:28PM UTC coverage: 92.003% (+0.7%) from 91.274%
11087146043

push

github

web-flow
Create terraform.yml

82959 of 90170 relevant lines covered (92.0%)

9376319.11 hits per line

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

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

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

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

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

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

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

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

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

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

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

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

91
BigInt::BigInt(const uint8_t input[], size_t length) {
226,544✔
92
   binary_decode(input, length);
226,544✔
93
}
226,544✔
94

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

102
//static
103
BigInt BigInt::from_bytes_with_max_bits(const uint8_t input[], size_t length, size_t max_bits) {
22,068✔
104
   const size_t input_bits = 8 * length;
22,068✔
105

106
   BigInt bn;
22,068✔
107
   bn.binary_decode(input, length);
22,068✔
108

109
   if(input_bits > max_bits) {
22,068✔
110
      const size_t bits_to_shift = input_bits - max_bits;
9,001✔
111

112
      bn >>= bits_to_shift;
9,001✔
113
   }
114

115
   return bn;
22,068✔
116
}
×
117

118
/*
119
* Construct a BigInt from an encoded BigInt
120
*/
121
BigInt::BigInt(RandomNumberGenerator& rng, size_t bits, bool set_high_bit) {
27,135✔
122
   randomize(rng, bits, set_high_bit);
27,135✔
123
}
27,135✔
124

125
uint8_t BigInt::byte_at(size_t n) const {
312,894✔
126
   return get_byte_var(sizeof(word) - (n % sizeof(word)) - 1, word_at(n / sizeof(word)));
312,894✔
127
}
128

129
int32_t BigInt::cmp_word(word other) const {
4,497,999✔
130
   if(is_negative()) {
4,497,999✔
131
      return -1;  // other is positive ...
132
   }
133

134
   const size_t sw = this->sig_words();
4,464,600✔
135
   if(sw > 1) {
4,464,600✔
136
      return 1;  // must be larger since other is just one word ...
137
   }
138

139
   return bigint_cmp(this->data(), sw, &other, 1);
2,148,262✔
140
}
141

142
/*
143
* Comparison Function
144
*/
145
int32_t BigInt::cmp(const BigInt& other, bool check_signs) const {
710,354✔
146
   if(check_signs) {
710,354✔
147
      if(other.is_positive() && this->is_negative()) {
710,227✔
148
         return -1;
149
      }
150

151
      if(other.is_negative() && this->is_positive()) {
710,163✔
152
         return 1;
153
      }
154

155
      if(other.is_negative() && this->is_negative()) {
710,099✔
156
         return (-bigint_cmp(this->data(), this->size(), other.data(), other.size()));
74✔
157
      }
158
   }
159

160
   return bigint_cmp(this->data(), this->size(), other.data(), other.size());
710,152✔
161
}
162

163
bool BigInt::is_equal(const BigInt& other) const {
420,009✔
164
   if(this->sign() != other.sign()) {
420,009✔
165
      return false;
166
   }
167

168
   return bigint_ct_is_eq(this->data(), this->sig_words(), other.data(), other.sig_words()).as_bool();
644,119✔
169
}
170

171
bool BigInt::is_less_than(const BigInt& other) const {
2,809,371✔
172
   if(this->is_negative() && other.is_positive()) {
2,809,371✔
173
      return true;
174
   }
175

176
   if(this->is_positive() && other.is_negative()) {
2,809,306✔
177
      return false;
178
   }
179

180
   if(other.is_negative() && this->is_negative()) {
2,809,244✔
181
      return bigint_ct_is_lt(other.data(), other.sig_words(), this->data(), this->sig_words()).as_bool();
73✔
182
   }
183

184
   return bigint_ct_is_lt(this->data(), this->sig_words(), other.data(), other.sig_words()).as_bool();
5,362,545✔
185
}
186

187
void BigInt::encode_words(word out[], size_t size) const {
2,741,802✔
188
   const size_t words = sig_words();
2,741,802✔
189

190
   if(words > size) {
2,741,802✔
191
      throw Encoding_Error("BigInt::encode_words value too large to encode");
×
192
   }
193

194
   clear_mem(out, size);
2,741,802✔
195
   copy_mem(out, data(), words);
2,741,802✔
196
}
2,741,802✔
197

198
size_t BigInt::Data::calc_sig_words() const {
108,859,388✔
199
   const size_t sz = m_reg.size();
108,859,388✔
200
   size_t sig = sz;
108,859,388✔
201

202
   word sub = 1;
108,859,388✔
203

204
   for(size_t i = 0; i != sz; ++i) {
1,835,958,071✔
205
      const word w = m_reg[sz - i - 1];
1,727,098,683✔
206
      sub &= ct_is_zero(w);
1,727,098,683✔
207
      sig -= sub;
1,727,098,683✔
208
   }
209

210
   /*
211
   * This depends on the data so is poisoned, but unpoison it here as
212
   * later conditionals are made on the size.
213
   */
214
   CT::unpoison(sig);
108,859,388✔
215

216
   return sig;
108,859,388✔
217
}
218

219
/*
220
* Return bits {offset...offset+length}
221
*/
222
uint32_t BigInt::get_substring(size_t offset, size_t length) const {
17,899,517✔
223
   if(length == 0 || length > 32) {
17,899,517✔
224
      throw Invalid_Argument("BigInt::get_substring invalid substring length");
×
225
   }
226

227
   const uint32_t mask = 0xFFFFFFFF >> (32 - length);
17,899,517✔
228

229
   const size_t word_offset = offset / BOTAN_MP_WORD_BITS;
17,899,517✔
230
   const size_t wshift = (offset % BOTAN_MP_WORD_BITS);
17,899,517✔
231

232
   /*
233
   * The substring is contained within one or at most two words. The
234
   * offset and length are not secret, so we can perform conditional
235
   * operations on those values.
236
   */
237
   const word w0 = word_at(word_offset);
17,899,517✔
238

239
   if(wshift == 0 || (offset + length) / BOTAN_MP_WORD_BITS == word_offset) {
17,899,517✔
240
      return static_cast<uint32_t>(w0 >> wshift) & mask;
17,045,495✔
241
   } else {
242
      const word w1 = word_at(word_offset + 1);
854,022✔
243
      return static_cast<uint32_t>((w0 >> wshift) | (w1 << (BOTAN_MP_WORD_BITS - wshift))) & mask;
854,022✔
244
   }
245
}
246

247
/*
248
* Convert this number to a uint32_t, if possible
249
*/
250
uint32_t BigInt::to_u32bit() const {
34,950✔
251
   if(is_negative()) {
34,950✔
252
      throw Encoding_Error("BigInt::to_u32bit: Number is negative");
×
253
   }
254
   if(bits() > 32) {
34,950✔
255
      throw Encoding_Error("BigInt::to_u32bit: Number is too big to convert");
15✔
256
   }
257

258
   uint32_t out = 0;
259
   for(size_t i = 0; i != 4; ++i) {
174,675✔
260
      out = (out << 8) | byte_at(3 - i);
139,740✔
261
   }
262
   return out;
34,935✔
263
}
264

265
/*
266
* Clear bit number n
267
*/
268
void BigInt::clear_bit(size_t n) {
23✔
269
   const size_t which = n / BOTAN_MP_WORD_BITS;
23✔
270

271
   if(which < size()) {
23✔
272
      const word mask = ~(static_cast<word>(1) << (n % BOTAN_MP_WORD_BITS));
23✔
273
      m_data.set_word_at(which, word_at(which) & mask);
23✔
274
   }
275
}
23✔
276

277
size_t BigInt::bytes() const {
236,393✔
278
   return round_up(bits(), 8) / 8;
236,393✔
279
}
280

281
size_t BigInt::top_bits_free() const {
2,740,520✔
282
   const size_t words = sig_words();
2,740,520✔
283

284
   const word top_word = word_at(words - 1);
21,924,160✔
285
   const size_t bits_used = high_bit(top_word);
2,740,520✔
286
   CT::unpoison(bits_used);
2,740,520✔
287
   return BOTAN_MP_WORD_BITS - bits_used;
2,740,520✔
288
}
289

290
size_t BigInt::bits() const {
2,097,067✔
291
   const size_t words = sig_words();
2,097,067✔
292

293
   if(words == 0) {
2,097,067✔
294
      return 0;
295
   }
296

297
   const size_t full_words = (words - 1) * BOTAN_MP_WORD_BITS;
2,077,417✔
298
   const size_t top_bits = BOTAN_MP_WORD_BITS - top_bits_free();
2,077,417✔
299

300
   return full_words + top_bits;
2,077,417✔
301
}
302

303
/*
304
* Return the negation of this number
305
*/
306
BigInt BigInt::operator-() const {
2,906✔
307
   BigInt x = (*this);
2,906✔
308
   x.flip_sign();
2,906✔
309
   return x;
2,906✔
310
}
×
311

312
size_t BigInt::reduce_below(const BigInt& p, secure_vector<word>& ws) {
26,747,063✔
313
   if(p.is_negative() || this->is_negative()) {
26,747,063✔
314
      throw Invalid_Argument("BigInt::reduce_below both values must be positive");
×
315
   }
316

317
   const size_t p_words = p.sig_words();
26,747,063✔
318

319
   if(size() < p_words + 1) {
26,747,063✔
320
      grow_to(p_words + 1);
11,133✔
321
   }
322

323
   if(ws.size() < p_words + 1) {
26,747,063✔
324
      ws.resize(p_words + 1);
663,103✔
325
   }
326

327
   clear_mem(ws.data(), ws.size());
26,747,063✔
328

329
   size_t reductions = 0;
330

331
   for(;;) {
69,176,731✔
332
      word borrow = bigint_sub3(ws.data(), data(), p_words + 1, p.data(), p_words);
138,353,462✔
333
      if(borrow) {
69,176,731✔
334
         break;
335
      }
336

337
      ++reductions;
42,429,668✔
338
      swap_reg(ws);
69,176,731✔
339
   }
340

341
   return reductions;
26,747,063✔
342
}
343

344
void BigInt::ct_reduce_below(const BigInt& mod, secure_vector<word>& ws, size_t bound) {
9,398,911✔
345
   if(mod.is_negative() || this->is_negative()) {
9,398,911✔
346
      throw Invalid_Argument("BigInt::ct_reduce_below both values must be positive");
×
347
   }
348

349
   const size_t mod_words = mod.sig_words();
9,398,911✔
350

351
   grow_to(mod_words);
9,398,911✔
352

353
   const size_t sz = size();
9,398,911✔
354

355
   ws.resize(sz);
9,398,911✔
356

357
   clear_mem(ws.data(), sz);
9,398,911✔
358

359
   for(size_t i = 0; i != bound; ++i) {
28,196,733✔
360
      word borrow = bigint_sub3(ws.data(), data(), sz, mod.data(), mod_words);
18,797,822✔
361

362
      CT::Mask<word>::is_zero(borrow).select_n(mutable_data(), ws.data(), data(), sz);
37,595,644✔
363
   }
364
}
9,398,911✔
365

366
/*
367
* Return the absolute value of this number
368
*/
369
BigInt BigInt::abs() const {
1,185✔
370
   BigInt x = (*this);
1,185✔
371
   x.set_sign(Positive);
1,185✔
372
   return x;
1,185✔
373
}
374

375
void BigInt::binary_encode(uint8_t buf[]) const {
83,285✔
376
   this->binary_encode(buf, bytes());
83,285✔
377
}
83,285✔
378

379
/*
380
* Encode this number into bytes
381
*/
382
void BigInt::binary_encode(uint8_t output[], size_t len) const {
116,534✔
383
   const size_t full_words = len / sizeof(word);
116,534✔
384
   const size_t extra_bytes = len % sizeof(word);
116,534✔
385

386
   for(size_t i = 0; i != full_words; ++i) {
1,257,183✔
387
      const word w = word_at(i);
1,140,649✔
388
      store_be(w, output + (len - (i + 1) * sizeof(word)));
1,140,649✔
389
   }
390

391
   if(extra_bytes > 0) {
116,534✔
392
      const word w = word_at(full_words);
54,464✔
393

394
      for(size_t i = 0; i != extra_bytes; ++i) {
220,968✔
395
         output[extra_bytes - i - 1] = get_byte_var(sizeof(word) - i - 1, w);
166,504✔
396
      }
397
   }
398
}
116,534✔
399

400
/*
401
* Set this number to the value in buf
402
*/
403
void BigInt::binary_decode(const uint8_t buf[], size_t length) {
612,441✔
404
   clear();
612,441✔
405

406
   const size_t full_words = length / sizeof(word);
612,441✔
407
   const size_t extra_bytes = length % sizeof(word);
612,441✔
408

409
   secure_vector<word> reg((round_up(full_words + (extra_bytes > 0 ? 1 : 0), 8)));
842,309✔
410

411
   for(size_t i = 0; i != full_words; ++i) {
4,298,494✔
412
      reg[i] = load_be<word>(buf + length - sizeof(word) * (i + 1), 0);
3,686,053✔
413
   }
414

415
   if(extra_bytes > 0) {
612,441✔
416
      for(size_t i = 0; i != extra_bytes; ++i) {
1,416,490✔
417
         reg[full_words] = (reg[full_words] << 8) | buf[i];
1,033,917✔
418
      }
419
   }
420

421
   m_data.swap(reg);
612,441✔
422
}
612,441✔
423

424
void BigInt::ct_cond_add(bool predicate, const BigInt& value) {
2,892,316✔
425
   if(this->is_negative() || value.is_negative()) {
2,892,316✔
426
      throw Invalid_Argument("BigInt::ct_cond_add requires both values to be positive");
×
427
   }
428
   this->grow_to(1 + value.sig_words());
2,892,316✔
429

430
   bigint_cnd_add(static_cast<word>(predicate), this->mutable_data(), this->size(), value.data(), value.sig_words());
2,892,316✔
431
}
2,892,316✔
432

433
void BigInt::ct_shift_left(size_t shift) {
30,285✔
434
   auto shl_bit = [](const BigInt& a, BigInt& result) {
9,868,096✔
435
      BOTAN_DEBUG_ASSERT(a.size() + 1 == result.size());
9,837,811✔
436
      bigint_shl2(result.mutable_data(), a.data(), a.size(), 1);
9,837,811✔
437
      // shl2 may have shifted a bit into the next word, which must be dropped
438
      clear_mem(result.mutable_data() + result.size() - 1, 1);
9,837,811✔
439
   };
9,837,811✔
440

441
   auto shl_word = [](const BigInt& a, BigInt& result) {
9,868,096✔
442
      // the most significant word is not copied, aka. shifted out
443
      bigint_shl2(result.mutable_data(), a.data(), a.size() - 1 /* ignore msw */, BOTAN_MP_WORD_BITS);
9,837,811✔
444
      // we left-shifted by a full word, the least significant word must be zero'ed
445
      clear_mem(result.mutable_data(), 1);
9,837,811✔
446
   };
9,837,811✔
447

448
   BOTAN_ASSERT_NOMSG(size() > 0);
30,285✔
449

450
   constexpr size_t bits_in_word = sizeof(word) * 8;
30,285✔
451
   const size_t word_shift = shift >> ceil_log2(bits_in_word);             // shift / bits_in_word
30,285✔
452
   const size_t bit_shift = shift & ((1 << ceil_log2(bits_in_word)) - 1);  // shift % bits_in_word
30,285✔
453
   const size_t iterations = std::max(size(), bits_in_word) - 1;           // uint64_t i; i << 64 is undefined behaviour
30,285✔
454

455
   // In every iteration, shift one bit and one word to the left and use the
456
   // shift results only when they are within the shift range.
457
   BigInt tmp;
30,285✔
458
   tmp.resize(size() + 1 /* to hold the shifted-out word */);
30,285✔
459
   for(size_t i = 0; i < iterations; ++i) {
9,868,096✔
460
      shl_bit(*this, tmp);
9,837,811✔
461
      ct_cond_assign(i < bit_shift, tmp);
9,837,811✔
462
      shl_word(*this, tmp);
9,837,811✔
463
      ct_cond_assign(i < word_shift, tmp);
9,837,811✔
464
   }
465
}
30,285✔
466

467
void BigInt::ct_cond_swap(bool predicate, BigInt& other) {
159,286,282✔
468
   const size_t max_words = std::max(size(), other.size());
159,286,282✔
469
   grow_to(max_words);
159,286,282✔
470
   other.grow_to(max_words);
159,286,282✔
471

472
   bigint_cnd_swap(static_cast<word>(predicate), this->mutable_data(), other.mutable_data(), max_words);
159,286,282✔
473
}
159,286,282✔
474

475
void BigInt::cond_flip_sign(bool predicate) {
55,520,784✔
476
   // This code is assuming Negative == 0, Positive == 1
477

478
   const auto mask = CT::Mask<uint8_t>::expand(predicate);
55,520,784✔
479

480
   const uint8_t current_sign = static_cast<uint8_t>(sign());
55,520,784✔
481

482
   const uint8_t new_sign = mask.select(current_sign ^ 1, current_sign);
55,520,784✔
483

484
   set_sign(static_cast<Sign>(new_sign));
55,520,784✔
485
}
55,520,784✔
486

487
void BigInt::ct_cond_assign(bool predicate, const BigInt& other) {
32,805,184✔
488
   const size_t t_words = size();
32,805,184✔
489
   const size_t o_words = other.size();
32,805,184✔
490

491
   if(o_words < t_words) {
32,805,184✔
492
      grow_to(o_words);
47,738✔
493
   }
494

495
   const size_t r_words = std::max(t_words, o_words);
32,805,184✔
496

497
   const auto mask = CT::Mask<word>::expand(predicate);
32,805,184✔
498

499
   for(size_t i = 0; i != r_words; ++i) {
2,147,483,647✔
500
      const word o_word = other.word_at(i);
2,147,483,647✔
501
      const word t_word = this->word_at(i);
2,147,483,647✔
502
      this->set_word_at(i, mask.select(o_word, t_word));
2,147,483,647✔
503
   }
504

505
   const bool different_sign = sign() != other.sign();
32,805,184✔
506
   cond_flip_sign(predicate && different_sign);
32,805,184✔
507
}
32,805,184✔
508

509
#if defined(BOTAN_HAS_VALGRIND)
510
void BigInt::const_time_poison() const {
511
   CT::poison(m_data.const_data(), m_data.size());
512
}
513

514
void BigInt::const_time_unpoison() const {
515
   CT::unpoison(m_data.const_data(), m_data.size());
516
}
517
#endif
518

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