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

randombit / botan / 5230455705

10 Jun 2023 02:30PM UTC coverage: 91.715% (-0.03%) from 91.746%
5230455705

push

github

randombit
Merge GH #3584 Change clang-format AllowShortFunctionsOnASingleLine config from All to Inline

77182 of 84154 relevant lines covered (91.72%)

11975295.43 hits per line

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

95.09
/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) {
231,355✔
19
#if BOTAN_MP_WORD_BITS == 64
20
   m_data.set_word_at(0, n);
231,355✔
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
}
231,355✔
26

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

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

41
//static
42
BigInt BigInt::from_word(word n) {
576,423✔
43
   BigInt bn;
576,423✔
44
   bn.set_word_at(0, n);
576,423✔
45
   return bn;
576,423✔
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) {
13,262,851✔
59
   BigInt bn;
13,262,851✔
60
   bn.grow_to(size);
13,262,851✔
61
   return bn;
13,262,851✔
62
}
×
63

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

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

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

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

84
   if(negative) {
47,066✔
85
      set_sign(Negative);
445✔
86
   } else {
87
      set_sign(Positive);
46,621✔
88
   }
89
}
47,066✔
90

91
BigInt::BigInt(const uint8_t input[], size_t length) {
211,219✔
92
   binary_decode(input, length);
211,219✔
93
}
211,219✔
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) {
21,275✔
104
   const size_t input_bits = 8 * length;
21,275✔
105

106
   BigInt bn;
21,275✔
107
   bn.binary_decode(input, length);
21,275✔
108

109
   if(input_bits > max_bits) {
21,275✔
110
      const size_t bits_to_shift = input_bits - max_bits;
8,944✔
111

112
      bn >>= bits_to_shift;
8,944✔
113
   }
114

115
   return bn;
21,275✔
116
}
×
117

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

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

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

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

139
   return bigint_cmp(this->data(), sw, &other, 1);
1,853,995✔
140
}
141

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

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

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

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

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

168
   return bigint_ct_is_eq(this->data(), this->sig_words(), other.data(), other.sig_words()).is_set();
589,009✔
169
}
170

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

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

180
   if(other.is_negative() && this->is_negative()) {
2,796,686✔
181
      return bigint_ct_is_lt(other.data(), other.sig_words(), this->data(), this->sig_words()).is_set();
71✔
182
   }
183

184
   return bigint_ct_is_lt(this->data(), this->sig_words(), other.data(), other.sig_words()).is_set();
5,347,180✔
185
}
186

187
void BigInt::encode_words(word out[], size_t size) const {
3,020,472✔
188
   const size_t words = sig_words();
3,020,472✔
189

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

194
   clear_mem(out, size);
3,020,472✔
195
   copy_mem(out, data(), words);
3,020,472✔
196
}
3,020,472✔
197

198
size_t BigInt::Data::calc_sig_words() const {
113,142,948✔
199
   const size_t sz = m_reg.size();
113,142,948✔
200
   size_t sig = sz;
113,142,948✔
201

202
   word sub = 1;
113,142,948✔
203

204
   for(size_t i = 0; i != sz; ++i) {
1,943,222,708✔
205
      const word w = m_reg[sz - i - 1];
1,830,079,760✔
206
      sub &= ct_is_zero(w);
1,830,079,760✔
207
      sig -= sub;
1,830,079,760✔
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);
113,142,948✔
215

216
   return sig;
113,142,948✔
217
}
218

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

227
   const uint32_t mask = 0xFFFFFFFF >> (32 - length);
16,474,541✔
228

229
   const size_t word_offset = offset / BOTAN_MP_WORD_BITS;
16,474,541✔
230
   const size_t wshift = (offset % BOTAN_MP_WORD_BITS);
16,474,541✔
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);
16,474,541✔
238

239
   if(wshift == 0 || (offset + length) / BOTAN_MP_WORD_BITS == word_offset) {
16,474,541✔
240
      return static_cast<uint32_t>(w0 >> wshift) & mask;
15,699,004✔
241
   } else {
242
      const word w1 = word_at(word_offset + 1);
775,537✔
243
      return static_cast<uint32_t>((w0 >> wshift) | (w1 << (BOTAN_MP_WORD_BITS - wshift))) & mask;
775,537✔
244
   }
245
}
246

247
/*
248
* Convert this number to a uint32_t, if possible
249
*/
250
uint32_t BigInt::to_u32bit() const {
34,948✔
251
   if(is_negative()) {
34,948✔
252
      throw Encoding_Error("BigInt::to_u32bit: Number is negative");
×
253
   }
254
   if(bits() > 32) {
34,948✔
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,665✔
260
      out = (out << 8) | byte_at(3 - i);
139,732✔
261
   }
262
   return out;
34,933✔
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 {
213,679✔
278
   return round_up(bits(), 8) / 8;
213,679✔
279
}
280

281
size_t BigInt::top_bits_free() const {
4,451,127✔
282
   const size_t words = sig_words();
4,451,127✔
283

284
   const word top_word = word_at(words - 1);
35,609,016✔
285
   const size_t bits_used = high_bit(top_word);
4,451,127✔
286
   CT::unpoison(bits_used);
4,451,127✔
287
   return BOTAN_MP_WORD_BITS - bits_used;
4,451,127✔
288
}
289

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

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

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

300
   return full_words + top_bits;
2,025,950✔
301
}
302

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

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

317
   const size_t p_words = p.sig_words();
26,176,701✔
318

319
   if(size() < p_words + 1) {
26,176,701✔
320
      grow_to(p_words + 1);
11,301✔
321
   }
322

323
   if(ws.size() < p_words + 1) {
26,176,701✔
324
      ws.resize(p_words + 1);
665,389✔
325
   }
326

327
   clear_mem(ws.data(), ws.size());
26,176,701✔
328

329
   size_t reductions = 0;
330

331
   for(;;) {
67,677,906✔
332
      word borrow = bigint_sub3(ws.data(), data(), p_words + 1, p.data(), p_words);
135,355,812✔
333
      if(borrow) {
67,677,906✔
334
         break;
335
      }
336

337
      ++reductions;
41,501,205✔
338
      swap_reg(ws);
67,677,906✔
339
   }
340

341
   return reductions;
26,176,701✔
342
}
343

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

349
   const size_t mod_words = mod.sig_words();
8,595,971✔
350

351
   grow_to(mod_words);
8,595,971✔
352

353
   const size_t sz = size();
8,595,971✔
354

355
   ws.resize(sz);
8,595,971✔
356

357
   clear_mem(ws.data(), sz);
8,595,971✔
358

359
   for(size_t i = 0; i != bound; ++i) {
25,787,913✔
360
      word borrow = bigint_sub3(ws.data(), data(), sz, mod.data(), mod_words);
17,191,942✔
361

362
      CT::Mask<word>::is_zero(borrow).select_n(mutable_data(), ws.data(), data(), sz);
34,383,884✔
363
   }
364
}
8,595,971✔
365

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

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

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

386
   for(size_t i = 0; i != full_words; ++i) {
1,154,382✔
387
      const word w = word_at(i);
1,048,929✔
388
      store_be(w, output + (len - (i + 1) * sizeof(word)));
1,048,929✔
389
   }
390

391
   if(extra_bytes > 0) {
105,453✔
392
      const word w = word_at(full_words);
47,714✔
393

394
      for(size_t i = 0; i != extra_bytes; ++i) {
196,120✔
395
         output[extra_bytes - i - 1] = get_byte_var(sizeof(word) - i - 1, w);
148,406✔
396
      }
397
   }
398
}
105,453✔
399

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

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

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

411
   for(size_t i = 0; i != full_words; ++i) {
3,952,690✔
412
      reg[i] = load_be<word>(buf + length - sizeof(word) * (i + 1), 0);
3,363,719✔
413
   }
414

415
   if(extra_bytes > 0) {
588,971✔
416
      for(size_t i = 0; i != extra_bytes; ++i) {
1,393,390✔
417
         reg[full_words] = (reg[full_words] << 8) | buf[i];
1,019,521✔
418
      }
419
   }
420

421
   m_data.swap(reg);
588,971✔
422
}
588,971✔
423

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

430
   bigint_cnd_add(static_cast<word>(predicate), this->mutable_data(), this->size(), value.data(), value.sig_words());
7,960,515✔
431
}
7,960,515✔
432

433
void BigInt::ct_cond_swap(bool predicate, BigInt& other) {
153,460,892✔
434
   const size_t max_words = std::max(size(), other.size());
153,460,892✔
435
   grow_to(max_words);
153,460,892✔
436
   other.grow_to(max_words);
153,460,892✔
437

438
   bigint_cnd_swap(predicate, this->mutable_data(), other.mutable_data(), max_words);
153,460,892✔
439
}
153,460,892✔
440

441
void BigInt::cond_flip_sign(bool predicate) {
22,598,470✔
442
   // This code is assuming Negative == 0, Positive == 1
443

444
   const auto mask = CT::Mask<uint8_t>::expand(predicate);
22,598,470✔
445

446
   const uint8_t current_sign = static_cast<uint8_t>(sign());
22,598,470✔
447

448
   const uint8_t new_sign = mask.select(current_sign ^ 1, current_sign);
22,598,470✔
449

450
   set_sign(static_cast<Sign>(new_sign));
22,598,470✔
451
}
22,598,470✔
452

453
void BigInt::ct_cond_assign(bool predicate, const BigInt& other) {
1,793,779✔
454
   const size_t t_words = size();
1,793,779✔
455
   const size_t o_words = other.size();
1,793,779✔
456

457
   if(o_words < t_words) {
1,793,779✔
458
      grow_to(o_words);
46,044✔
459
   }
460

461
   const size_t r_words = std::max(t_words, o_words);
1,793,779✔
462

463
   const auto mask = CT::Mask<word>::expand(predicate);
1,793,779✔
464

465
   for(size_t i = 0; i != r_words; ++i) {
29,055,204✔
466
      const word o_word = other.word_at(i);
27,261,425✔
467
      const word t_word = this->word_at(i);
27,261,425✔
468
      this->set_word_at(i, mask.select(o_word, t_word));
27,261,425✔
469
   }
470

471
   const bool different_sign = sign() != other.sign();
1,793,779✔
472
   cond_flip_sign(predicate && different_sign);
1,793,779✔
473
}
1,793,779✔
474

475
#if defined(BOTAN_HAS_VALGRIND)
476
void BigInt::const_time_poison() const {
477
   CT::poison(m_data.const_data(), m_data.size());
478
}
479

480
void BigInt::const_time_unpoison() const {
481
   CT::unpoison(m_data.const_data(), m_data.size());
482
}
483
#endif
484

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