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

randombit / botan / 14606431966

22 Apr 2025 11:19PM UTC coverage: 91.416% (+0.1%) from 91.316%
14606431966

Pull #4835

github

web-flow
Merge f63084710 into 4c413a8ac
Pull Request #4835: New Barrett Reduction implementation

95800 of 104796 relevant lines covered (91.42%)

13215574.08 hits per line

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

88.97
/src/lib/math/bigint/big_ops2.cpp
1
/*
2
* (C) 1999-2007,2018 Jack Lloyd
3
*     2016 Matthias Gierlings
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/mp_core.h>
12
#include <algorithm>
13

14
namespace Botan {
15

16
BigInt& BigInt::add(const word y[], size_t y_words, Sign y_sign) {
6,071,715✔
17
   const size_t x_sw = sig_words();
6,071,715✔
18

19
   grow_to(std::max(x_sw, y_words) + 1);
6,142,632✔
20

21
   if(sign() == y_sign) {
6,071,715✔
22
      bigint_add2(mutable_data(), size() - 1, y, y_words);
2,469,406✔
23
   } else {
24
      const int32_t relative_size = bigint_cmp(_data(), x_sw, y, y_words);
3,602,309✔
25

26
      if(relative_size >= 0) {
3,602,309✔
27
         // *this >= y
28
         bigint_sub2(mutable_data(), x_sw, y, y_words);
3,544,006✔
29
      } else {
30
         // *this < y
31
         bigint_sub2_rev(mutable_data(), y, y_words);
58,303✔
32
      }
33

34
      //this->sign_fixup(relative_size, y_sign);
35
      if(relative_size < 0) {
3,602,309✔
36
         set_sign(y_sign);
58,303✔
37
      } else if(relative_size == 0) {
3,544,006✔
38
         set_sign(Positive);
53,105✔
39
      }
40
   }
41

42
   return (*this);
6,071,715✔
43
}
44

45
BigInt& BigInt::mod_add(const BigInt& s, const BigInt& mod, secure_vector<word>& ws) {
1,115,392✔
46
   if(this->is_negative() || s.is_negative() || mod.is_negative()) {
1,115,392✔
47
      throw Invalid_Argument("BigInt::mod_add expects all arguments are positive");
×
48
   }
49

50
   BOTAN_DEBUG_ASSERT(*this < mod);
1,115,392✔
51
   BOTAN_DEBUG_ASSERT(s < mod);
1,115,392✔
52

53
   /*
54
   t + s or t + s - p == t - (p - s)
55

56
   So first compute ws = p - s
57

58
   Then compute t + s and t - ws
59

60
   If t - ws does not borrow, then that is the correct valued
61
   */
62

63
   const size_t mod_sw = mod.sig_words();
1,115,392✔
64
   BOTAN_ARG_CHECK(mod_sw > 0, "BigInt::mod_add modulus must be positive");
1,115,392✔
65

66
   this->grow_to(mod_sw);
1,115,392✔
67
   s.grow_to(mod_sw);
1,115,392✔
68

69
   // First mod_sw for p - s, 2*mod_sw for bigint_addsub workspace
70
   if(ws.size() < 3 * mod_sw) {
1,115,392✔
71
      ws.resize(3 * mod_sw);
614,864✔
72
   }
73

74
   word borrow = bigint_sub3(&ws[0], mod._data(), mod_sw, s._data(), mod_sw);
1,115,392✔
75
   BOTAN_DEBUG_ASSERT(borrow == 0);
1,115,392✔
76
   BOTAN_UNUSED(borrow);
1,115,392✔
77

78
   // Compute t - ws
79
   borrow = bigint_sub3(&ws[mod_sw], this->_data(), mod_sw, &ws[0], mod_sw);
1,115,392✔
80

81
   // Compute t + s
82
   bigint_add3_nc(&ws[mod_sw * 2], this->_data(), mod_sw, s._data(), mod_sw);
1,115,392✔
83

84
   CT::conditional_copy_mem(borrow, &ws[0], &ws[mod_sw * 2], &ws[mod_sw], mod_sw);
1,115,392✔
85
   set_words(&ws[0], mod_sw);
1,115,392✔
86

87
   return (*this);
1,115,392✔
88
}
89

90
BigInt& BigInt::mod_sub(const BigInt& s, const BigInt& mod, secure_vector<word>& ws) {
15,863,593✔
91
   if(this->is_negative() || s.is_negative() || mod.is_negative()) {
15,863,593✔
92
      throw Invalid_Argument("BigInt::mod_sub expects all arguments are positive");
×
93
   }
94

95
   // We are assuming in this function that *this and s are no more than mod_sw words long
96
   BOTAN_DEBUG_ASSERT(*this < mod);
15,863,593✔
97
   BOTAN_DEBUG_ASSERT(s < mod);
15,863,593✔
98

99
   const size_t mod_sw = mod.sig_words();
15,863,593✔
100

101
   this->grow_to(mod_sw);
15,863,593✔
102
   s.grow_to(mod_sw);
15,863,593✔
103

104
   if(ws.size() < mod_sw) {
15,863,593✔
105
      ws.resize(mod_sw);
5,997✔
106
   }
107

108
   bigint_mod_sub(mutable_data(), s._data(), mod._data(), mod_sw, ws.data());
15,863,593✔
109

110
   return (*this);
15,863,593✔
111
}
112

113
BigInt& BigInt::mod_mul(uint8_t y, const BigInt& mod, secure_vector<word>& ws) {
6,908,632✔
114
   BOTAN_ARG_CHECK(this->is_negative() == false, "*this must be positive");
6,908,632✔
115
   BOTAN_ARG_CHECK(y < 16, "y too large");
6,908,632✔
116

117
   BOTAN_DEBUG_ASSERT(*this < mod);
6,908,632✔
118

119
   *this *= static_cast<word>(y);
6,908,632✔
120
   this->reduce_below(mod, ws);
6,908,632✔
121
   return (*this);
6,908,632✔
122
}
123

124
BigInt& BigInt::rev_sub(const word y[], size_t y_sw, secure_vector<word>& ws) {
×
125
   if(this->sign() != BigInt::Positive) {
×
126
      throw Invalid_State("BigInt::sub_rev requires this is positive");
×
127
   }
128

129
   const size_t x_sw = this->sig_words();
×
130

131
   ws.resize(std::max(x_sw, y_sw));
×
132
   clear_mem(ws.data(), ws.size());
×
133

134
   const int32_t relative_size = bigint_sub_abs(ws.data(), _data(), x_sw, y, y_sw);
×
135

136
   this->cond_flip_sign(relative_size > 0);
×
137
   this->swap_reg(ws);
×
138

139
   return (*this);
×
140
}
141

142
/*
143
* Multiplication Operator
144
*/
145
BigInt& BigInt::operator*=(const BigInt& y) {
530✔
146
   secure_vector<word> ws;
530✔
147
   return this->mul(y, ws);
530✔
148
}
530✔
149

150
BigInt& BigInt::mul(const BigInt& y, secure_vector<word>& ws) {
9,713✔
151
   const size_t x_sw = sig_words();
9,713✔
152
   const size_t y_sw = y.sig_words();
9,713✔
153
   set_sign((sign() == y.sign()) ? Positive : Negative);
9,783✔
154

155
   if(x_sw == 0 || y_sw == 0) {
9,713✔
156
      clear();
33✔
157
      set_sign(Positive);
33✔
158
   } else if(x_sw == 1 && y_sw) {
9,680✔
159
      grow_to(y_sw + 1);
332✔
160
      bigint_linmul3(mutable_data(), y._data(), y_sw, word_at(0));
664✔
161
   } else if(y_sw == 1 && x_sw) {
9,348✔
162
      word carry = bigint_linmul2(mutable_data(), x_sw, y.word_at(0));
42✔
163
      set_word_at(x_sw, carry);
21✔
164
   } else {
165
      const size_t new_size = x_sw + y_sw + 1;
9,327✔
166
      if(ws.size() < new_size) {
9,327✔
167
         ws.resize(new_size);
9,327✔
168
      }
169
      secure_vector<word> z_reg(new_size);
9,327✔
170

171
      bigint_mul(z_reg.data(), z_reg.size(), _data(), size(), x_sw, y._data(), y.size(), y_sw, ws.data(), ws.size());
9,327✔
172

173
      this->swap_reg(z_reg);
9,327✔
174
   }
9,327✔
175

176
   return (*this);
9,713✔
177
}
178

179
BigInt& BigInt::square(secure_vector<word>& ws) {
10,204✔
180
   const size_t sw = sig_words();
10,204✔
181

182
   secure_vector<word> z(2 * sw);
10,204✔
183
   ws.resize(z.size());
10,204✔
184

185
   bigint_sqr(z.data(), z.size(), _data(), size(), sw, ws.data(), ws.size());
10,204✔
186

187
   swap_reg(z);
10,204✔
188
   set_sign(BigInt::Positive);
10,204✔
189

190
   return (*this);
10,204✔
191
}
10,204✔
192

193
BigInt& BigInt::operator*=(word y) {
7,287,759✔
194
   if(y == 0) {
7,287,759✔
195
      clear();
×
196
      set_sign(Positive);
×
197
   }
198

199
   const word carry = bigint_linmul2(mutable_data(), size(), y);
7,287,759✔
200
   set_word_at(size(), carry);
7,287,759✔
201

202
   return (*this);
7,287,759✔
203
}
204

205
/*
206
* Division Operator
207
*/
208
BigInt& BigInt::operator/=(const BigInt& y) {
929✔
209
   if(y.sig_words() == 1 && is_power_of_2(y.word_at(0))) {
1,622✔
210
      (*this) >>= (y.bits() - 1);
85✔
211
   } else {
212
      (*this) = (*this) / y;
844✔
213
   }
214
   return (*this);
929✔
215
}
216

217
/*
218
* Modulo Operator
219
*/
220
BigInt& BigInt::operator%=(const BigInt& mod) {
323,374✔
221
   return (*this = (*this) % mod);
323,374✔
222
}
223

224
/*
225
* Modulo Operator
226
*/
227
word BigInt::operator%=(word mod) {
33✔
228
   if(mod == 0) {
33✔
229
      throw Invalid_Argument("BigInt::operator%= divide by zero");
×
230
   }
231

232
   word remainder = 0;
33✔
233

234
   if(is_power_of_2(mod)) {
33✔
235
      remainder = (word_at(0) & (mod - 1));
10✔
236
   } else {
237
      const size_t sw = sig_words();
28✔
238
      for(size_t i = sw; i > 0; --i) {
79✔
239
         remainder = bigint_modop_vartime(remainder, word_at(i - 1), mod);
102✔
240
      }
241
   }
242

243
   if(remainder && sign() == BigInt::Negative) {
33✔
244
      remainder = mod - remainder;
12✔
245
   }
246

247
   m_data.set_to_zero();
33✔
248
   m_data.set_word_at(0, remainder);
33✔
249
   set_sign(BigInt::Positive);
33✔
250
   return remainder;
33✔
251
}
252

253
/*
254
* Left Shift Operator
255
*/
256
BigInt& BigInt::operator<<=(size_t shift) {
12,139,179✔
257
   const size_t sw = sig_words();
12,139,179✔
258
   const size_t new_size = sw + (shift + WordInfo<word>::bits - 1) / WordInfo<word>::bits;
12,139,179✔
259

260
   m_data.grow_to(new_size);
12,139,179✔
261

262
   bigint_shl1(m_data.mutable_data(), new_size, sw, shift);
12,139,179✔
263

264
   return (*this);
12,139,179✔
265
}
266

267
/*
268
* Right Shift Operator
269
*/
270
BigInt& BigInt::operator>>=(size_t shift) {
8,085,829✔
271
   bigint_shr1(m_data.mutable_data(), m_data.size(), shift);
8,085,829✔
272

273
   if(is_negative() && is_zero()) {
8,180,012✔
274
      set_sign(Positive);
8✔
275
   }
276

277
   return (*this);
8,085,829✔
278
}
279

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