Coverage Report

Created: 2025-04-11 06:34

/src/botan/build/include/internal/botan/internal/bit_ops.h
Line
Count
Source (jump to first uncovered line)
1
/*
2
* Bit/Word Operations
3
* (C) 1999-2008 Jack Lloyd
4
* (C) Copyright Projet SECRET, INRIA, Rocquencourt
5
* (C) Bhaskar Biswas and  Nicolas Sendrier
6
* (C) 2014 cryptosource GmbH
7
* (C) 2014 Falko Strenzke fstrenzke@cryptosource.de
8
*
9
* Botan is released under the Simplified BSD License (see license.txt)
10
*/
11
12
#ifndef BOTAN_BIT_OPS_H_
13
#define BOTAN_BIT_OPS_H_
14
15
#include <botan/types.h>
16
17
#include <botan/compiler.h>
18
#include <botan/internal/bswap.h>
19
20
namespace Botan {
21
22
/**
23
* If top bit of arg is set, return ~0. Otherwise return 0.
24
*/
25
template <typename T>
26
inline constexpr T expand_top_bit(T a)
27
   requires(std::is_integral<T>::value)
28
2.99G
{
29
2.99G
   return static_cast<T>(0) - (a >> (sizeof(T) * 8 - 1));
30
2.99G
}
_ZN5Botan14expand_top_bitImEET_S1_Qsr3std11is_integralIS1_EE5value
Line
Count
Source
28
2.91G
{
29
2.91G
   return static_cast<T>(0) - (a >> (sizeof(T) * 8 - 1));
30
2.91G
}
_ZN5Botan14expand_top_bitIjEET_S1_Qsr3std11is_integralIS1_EE5value
Line
Count
Source
28
60.8M
{
29
60.8M
   return static_cast<T>(0) - (a >> (sizeof(T) * 8 - 1));
30
60.8M
}
_ZN5Botan14expand_top_bitIhEET_S1_Qsr3std11is_integralIS1_EE5value
Line
Count
Source
28
19.6M
{
29
19.6M
   return static_cast<T>(0) - (a >> (sizeof(T) * 8 - 1));
30
19.6M
}
_ZN5Botan14expand_top_bitIiEET_S1_Qsr3std11is_integralIS1_EE5value
Line
Count
Source
28
180
{
29
180
   return static_cast<T>(0) - (a >> (sizeof(T) * 8 - 1));
30
180
}
_ZN5Botan14expand_top_bitItEET_S1_Qsr3std11is_integralIS1_EE5value
Line
Count
Source
28
64.7k
{
29
64.7k
   return static_cast<T>(0) - (a >> (sizeof(T) * 8 - 1));
30
64.7k
}
31
32
/**
33
* If arg is zero, return ~0. Otherwise return 0
34
*/
35
template <typename T>
36
inline constexpr T ct_is_zero(T x)
37
   requires(std::is_integral<T>::value)
38
2.78G
{
39
2.78G
   return expand_top_bit<T>(~x & (x - 1));
40
2.78G
}
_ZN5Botan10ct_is_zeroImEET_S1_Qsr3std11is_integralIS1_EE5value
Line
Count
Source
38
2.70G
{
39
2.70G
   return expand_top_bit<T>(~x & (x - 1));
40
2.70G
}
_ZN5Botan10ct_is_zeroIjEET_S1_Qsr3std11is_integralIS1_EE5value
Line
Count
Source
38
60.8M
{
39
60.8M
   return expand_top_bit<T>(~x & (x - 1));
40
60.8M
}
_ZN5Botan10ct_is_zeroIhEET_S1_Qsr3std11is_integralIS1_EE5value
Line
Count
Source
38
19.6M
{
39
19.6M
   return expand_top_bit<T>(~x & (x - 1));
40
19.6M
}
_ZN5Botan10ct_is_zeroIiEET_S1_Qsr3std11is_integralIS1_EE5value
Line
Count
Source
38
180
{
39
180
   return expand_top_bit<T>(~x & (x - 1));
40
180
}
_ZN5Botan10ct_is_zeroItEET_S1_Qsr3std11is_integralIS1_EE5value
Line
Count
Source
38
32.3k
{
39
32.3k
   return expand_top_bit<T>(~x & (x - 1));
40
32.3k
}
41
42
/**
43
* Power of 2 test. T should be an unsigned integer type
44
* @param arg an integer value
45
* @return true iff arg is 2^n for some n > 0
46
*/
47
template <typename T>
48
inline constexpr bool is_power_of_2(T arg)
49
   requires(std::is_unsigned<T>::value)
50
276k
{
51
276k
   return (arg != 0) && (arg != 1) && ((arg & static_cast<T>(arg - 1)) == 0);
52
276k
}
_ZN5Botan13is_power_of_2ImEEbT_Qsr3std11is_unsignedIS1_EE5value
Line
Count
Source
50
276k
{
51
276k
   return (arg != 0) && (arg != 1) && ((arg & static_cast<T>(arg - 1)) == 0);
52
276k
}
Unexecuted instantiation: _ZN5Botan13is_power_of_2IjEEbT_Qsr3std11is_unsignedIS1_EE5value
53
54
/**
55
* Return the index of the highest set bit
56
* T is an unsigned integer type
57
* @param n an integer value
58
* @return index of the highest set bit in n
59
*/
60
template <typename T>
61
inline constexpr size_t high_bit(T n)
62
   requires(std::is_unsigned<T>::value)
63
580k
{
64
580k
   size_t hb = 0;
65
66
3.89M
   for(size_t s = 8 * sizeof(T) / 2; s > 0; s /= 2) {
67
3.31M
      const size_t z = s * ((~ct_is_zero(n >> s)) & 1);
68
3.31M
      hb += z;
69
3.31M
      n >>= z;
70
3.31M
   }
71
72
580k
   hb += n;
73
74
580k
   return hb;
75
580k
}
_ZN5Botan8high_bitImEEmT_Qsr3std11is_unsignedIS1_EE5value
Line
Count
Source
63
406k
{
64
406k
   size_t hb = 0;
65
66
2.84M
   for(size_t s = 8 * sizeof(T) / 2; s > 0; s /= 2) {
67
2.43M
      const size_t z = s * ((~ct_is_zero(n >> s)) & 1);
68
2.43M
      hb += z;
69
2.43M
      n >>= z;
70
2.43M
   }
71
72
406k
   hb += n;
73
74
406k
   return hb;
75
406k
}
Unexecuted instantiation: _ZN5Botan8high_bitItEEmT_Qsr3std11is_unsignedIS1_EE5value
_ZN5Botan8high_bitIjEEmT_Qsr3std11is_unsignedIS1_EE5value
Line
Count
Source
63
174k
{
64
174k
   size_t hb = 0;
65
66
1.04M
   for(size_t s = 8 * sizeof(T) / 2; s > 0; s /= 2) {
67
870k
      const size_t z = s * ((~ct_is_zero(n >> s)) & 1);
68
870k
      hb += z;
69
870k
      n >>= z;
70
870k
   }
71
72
174k
   hb += n;
73
74
174k
   return hb;
75
174k
}
_ZN5Botan8high_bitIhEEmT_Qsr3std11is_unsignedIS1_EE5value
Line
Count
Source
63
60
{
64
60
   size_t hb = 0;
65
66
240
   for(size_t s = 8 * sizeof(T) / 2; s > 0; s /= 2) {
67
180
      const size_t z = s * ((~ct_is_zero(n >> s)) & 1);
68
180
      hb += z;
69
180
      n >>= z;
70
180
   }
71
72
60
   hb += n;
73
74
60
   return hb;
75
60
}
76
77
/**
78
* Return the number of significant bytes in n
79
* @param n an integer value
80
* @return number of significant bytes in n
81
*/
82
template <typename T>
83
inline constexpr size_t significant_bytes(T n)
84
   requires(std::is_integral<T>::value)
85
50.3k
{
86
50.3k
   size_t b = 0;
87
88
201k
   for(size_t s = 8 * sizeof(n) / 2; s >= 8; s /= 2) {
89
150k
      const size_t z = s * (~ct_is_zero(n >> s) & 1);
90
150k
      b += z / 8;
91
150k
      n >>= z;
92
150k
   }
93
94
50.3k
   b += (n != 0);
95
96
50.3k
   return b;
97
50.3k
}
98
99
/**
100
* Count the trailing zero bits in n
101
* @param n an integer value
102
* @return maximum x st 2^x divides n
103
*/
104
template <typename T>
105
inline constexpr size_t ctz(T n)
106
   requires(std::is_integral<T>::value)
107
36.0M
{
108
   /*
109
   * If n == 0 then this function will compute 8*sizeof(T)-1, so
110
   * initialize lb to 1 if n == 0 to produce the expected result.
111
   */
112
36.0M
   size_t lb = ct_is_zero(n) & 1;
113
114
252M
   for(size_t s = 8 * sizeof(T) / 2; s > 0; s /= 2) {
115
216M
      const T mask = (static_cast<T>(1) << s) - 1;
116
216M
      const size_t z = s * (ct_is_zero(n & mask) & 1);
117
216M
      lb += z;
118
216M
      n >>= z;
119
216M
   }
120
121
36.0M
   return lb;
122
36.0M
}
_ZN5Botan3ctzImEEmT_Qsr3std11is_integralIS1_EE5value
Line
Count
Source
107
36.0M
{
108
   /*
109
   * If n == 0 then this function will compute 8*sizeof(T)-1, so
110
   * initialize lb to 1 if n == 0 to produce the expected result.
111
   */
112
36.0M
   size_t lb = ct_is_zero(n) & 1;
113
114
252M
   for(size_t s = 8 * sizeof(T) / 2; s > 0; s /= 2) {
115
216M
      const T mask = (static_cast<T>(1) << s) - 1;
116
216M
      const size_t z = s * (ct_is_zero(n & mask) & 1);
117
216M
      lb += z;
118
216M
      n >>= z;
119
216M
   }
120
121
36.0M
   return lb;
122
36.0M
}
Unexecuted instantiation: _ZN5Botan3ctzIjEEmT_Qsr3std11is_integralIS1_EE5value
123
124
template <typename T>
125
inline constexpr T floor_log2(T n)
126
   requires(std::is_unsigned<T>::value)
127
0
{
128
0
   BOTAN_ARG_CHECK(n != 0, "log2(0) is not defined");
129
0
   return static_cast<T>(high_bit(n) - 1);
130
0
}
Unexecuted instantiation: _ZN5Botan10floor_log2ItEET_S1_Qsr3std11is_unsignedIS1_EE5value
Unexecuted instantiation: _ZN5Botan10floor_log2ImEET_S1_Qsr3std11is_unsignedIS1_EE5value
131
132
template <typename T>
133
constexpr uint8_t ceil_log2(T x)
134
   requires(std::is_integral<T>::value && sizeof(T) < 32)
135
902
{
136
902
   if(x >> (sizeof(T) * 8 - 1)) {
137
0
      return sizeof(T) * 8;
138
0
   }
139
140
902
   uint8_t result = 0;
141
902
   T compare = 1;
142
143
6.93k
   while(compare < x) {
144
6.03k
      compare <<= 1;
145
6.03k
      result++;
146
6.03k
   }
147
148
902
   return result;
149
902
}
_ZN5Botan9ceil_log2ImEEhT_Qaasr3std11is_integralIS1_EE5valueltstS1_Li32E
Line
Count
Source
135
766
{
136
766
   if(x >> (sizeof(T) * 8 - 1)) {
137
0
      return sizeof(T) * 8;
138
0
   }
139
140
766
   uint8_t result = 0;
141
766
   T compare = 1;
142
143
5.87k
   while(compare < x) {
144
5.10k
      compare <<= 1;
145
5.10k
      result++;
146
5.10k
   }
147
148
766
   return result;
149
766
}
_ZN5Botan9ceil_log2IjEEhT_Qaasr3std11is_integralIS1_EE5valueltstS1_Li32E
Line
Count
Source
135
136
{
136
136
   if(x >> (sizeof(T) * 8 - 1)) {
137
0
      return sizeof(T) * 8;
138
0
   }
139
140
136
   uint8_t result = 0;
141
136
   T compare = 1;
142
143
1.06k
   while(compare < x) {
144
926
      compare <<= 1;
145
926
      result++;
146
926
   }
147
148
136
   return result;
149
136
}
150
151
/**
152
 * Ceil of an unsigned integer division. @p b must not be zero.
153
 *
154
 * @param a divident
155
 * @param b divisor
156
 *
157
 * @returns ceil(a/b)
158
 */
159
template <std::unsigned_integral T>
160
0
inline constexpr T ceil_division(T a, T b) {
161
0
   return (a + b - 1) / b;
162
0
}
163
164
/**
165
 * Return the number of bytes necessary to contain @p bits bits.
166
 */
167
template <typename T>
168
inline constexpr T ceil_tobytes(T bits)
169
   requires(std::is_integral<T>::value)
170
361
{
171
361
   return (bits + 7) / 8;
172
361
}
Unexecuted instantiation: _ZN5Botan12ceil_tobytesIhEET_S1_Qsr3std11is_integralIS1_EE5value
_ZN5Botan12ceil_tobytesIjEET_S1_Qsr3std11is_integralIS1_EE5value
Line
Count
Source
170
272
{
171
272
   return (bits + 7) / 8;
172
272
}
_ZN5Botan12ceil_tobytesImEET_S1_Qsr3std11is_integralIS1_EE5value
Line
Count
Source
170
89
{
171
89
   return (bits + 7) / 8;
172
89
}
Unexecuted instantiation: _ZN5Botan12ceil_tobytesIiEET_S1_Qsr3std11is_integralIS1_EE5value
173
174
// Potentially variable time ctz used for OCB
175
819
inline constexpr size_t var_ctz32(uint32_t n) {
176
819
#if BOTAN_COMPILER_HAS_BUILTIN(__builtin_ctz)
177
819
   if(n == 0) {
178
0
      return 32;
179
0
   }
180
819
   return __builtin_ctz(n);
181
#else
182
   return ctz<uint32_t>(n);
183
#endif
184
819
}
185
186
template <typename T>
187
0
inline constexpr T bit_permute_step(T x, T mask, size_t shift) {
188
   /*
189
   See https://reflectionsonsecurity.wordpress.com/2014/05/11/efficient-bit-permutation-using-delta-swaps/
190
   and http://programming.sirrida.de/bit_perm.html
191
   */
192
0
   const T swap = ((x >> shift) ^ x) & mask;
193
0
   return (x ^ swap) ^ (swap << shift);
194
0
}
Unexecuted instantiation: unsigned long Botan::bit_permute_step<unsigned long>(unsigned long, unsigned long, unsigned long)
Unexecuted instantiation: unsigned int Botan::bit_permute_step<unsigned int>(unsigned int, unsigned int, unsigned long)
195
196
template <typename T>
197
0
inline constexpr void swap_bits(T& x, T& y, T mask, size_t shift) {
198
0
   const T swap = ((x >> shift) ^ y) & mask;
199
0
   x ^= swap << shift;
200
0
   y ^= swap;
201
0
}
202
203
template <typename T>
204
7.23G
inline constexpr T choose(T mask, T a, T b) {
205
   //return (mask & a) | (~mask & b);
206
7.23G
   return (b ^ (mask & (a ^ b)));
207
7.23G
}
unsigned long Botan::choose<unsigned long>(unsigned long, unsigned long, unsigned long)
Line
Count
Source
204
7.14G
inline constexpr T choose(T mask, T a, T b) {
205
   //return (mask & a) | (~mask & b);
206
7.14G
   return (b ^ (mask & (a ^ b)));
207
7.14G
}
unsigned char Botan::choose<unsigned char>(unsigned char, unsigned char, unsigned char)
Line
Count
Source
204
18.8M
inline constexpr T choose(T mask, T a, T b) {
205
   //return (mask & a) | (~mask & b);
206
18.8M
   return (b ^ (mask & (a ^ b)));
207
18.8M
}
Unexecuted instantiation: unsigned short Botan::choose<unsigned short>(unsigned short, unsigned short, unsigned short)
unsigned int Botan::choose<unsigned int>(unsigned int, unsigned int, unsigned int)
Line
Count
Source
204
78.4M
inline constexpr T choose(T mask, T a, T b) {
205
   //return (mask & a) | (~mask & b);
206
78.4M
   return (b ^ (mask & (a ^ b)));
207
78.4M
}
208
209
template <typename T>
210
45.6M
inline constexpr T majority(T a, T b, T c) {
211
   /*
212
   Considering each bit of a, b, c individually
213
214
   If a xor b is set, then c is the deciding vote.
215
216
   If a xor b is not set then either a and b are both set or both unset.
217
   In either case the value of c doesn't matter, and examining b (or a)
218
   allows us to determine which case we are in.
219
   */
220
45.6M
   return choose(a ^ b, c, b);
221
45.6M
}
unsigned int Botan::majority<unsigned int>(unsigned int, unsigned int, unsigned int)
Line
Count
Source
210
38.9M
inline constexpr T majority(T a, T b, T c) {
211
   /*
212
   Considering each bit of a, b, c individually
213
214
   If a xor b is set, then c is the deciding vote.
215
216
   If a xor b is not set then either a and b are both set or both unset.
217
   In either case the value of c doesn't matter, and examining b (or a)
218
   allows us to determine which case we are in.
219
   */
220
38.9M
   return choose(a ^ b, c, b);
221
38.9M
}
unsigned long Botan::majority<unsigned long>(unsigned long, unsigned long, unsigned long)
Line
Count
Source
210
6.75M
inline constexpr T majority(T a, T b, T c) {
211
   /*
212
   Considering each bit of a, b, c individually
213
214
   If a xor b is set, then c is the deciding vote.
215
216
   If a xor b is not set then either a and b are both set or both unset.
217
   In either case the value of c doesn't matter, and examining b (or a)
218
   allows us to determine which case we are in.
219
   */
220
6.75M
   return choose(a ^ b, c, b);
221
6.75M
}
222
223
/**
224
 * @returns the reversed bits in @p b.
225
 */
226
template <std::unsigned_integral T>
227
0
constexpr T ct_reverse_bits(T b) {
228
0
   auto extend = [](uint8_t m) -> T {
229
0
      T mask = 0;
230
0
      for(size_t i = 0; i < sizeof(T); ++i) {
231
0
         mask |= T(m) << i * 8;
232
0
      }
233
0
      return mask;
234
0
   };
235
236
   // First reverse bits in each byte...
237
   // From: https://stackoverflow.com/a/2602885
238
0
   b = (b & extend(0xF0)) >> 4 | (b & extend(0x0F)) << 4;
239
0
   b = (b & extend(0xCC)) >> 2 | (b & extend(0x33)) << 2;
240
0
   b = (b & extend(0xAA)) >> 1 | (b & extend(0x55)) << 1;
241
242
   // ... then swap the bytes
243
0
   return reverse_bytes(b);
244
0
}
245
246
/**
247
 * Calculates the number of 1-bits in an unsigned integer in constant-time.
248
 * This operation is also known as "population count" or hamming weight.
249
 *
250
 * Modern compilers will recognize this pattern and replace it by a hardware
251
 * instruction, if available. This is the SWAR (SIMD within a register)
252
 * algorithm. See: https://nimrod.blog/posts/algorithms-behind-popcount/#swar-algorithm
253
 *
254
 * Note: C++20 provides std::popcount(), but there's no guarantee that this
255
 *       is implemented in constant-time.
256
 *
257
 * @param x an unsigned integer
258
 * @returns the number of 1-bits in the provided value
259
 */
260
template <std::unsigned_integral T>
261
0
inline constexpr uint8_t ct_popcount(T x) {
262
0
   constexpr size_t s = sizeof(T);
263
0
   static_assert(s <= 8, "T is not a suitable unsigned integer value");
264
0
   if constexpr(s == 8) {
265
0
      x = x - ((x >> 1) & 0x5555555555555555);
266
0
      x = (x & 0x3333333333333333) + ((x >> 2) & 0x3333333333333333);
267
0
      x = (x + (x >> 4)) & 0xF0F0F0F0F0F0F0F;
268
0
      return (x * 0x101010101010101) >> 56;
269
   } else if constexpr(s == 4) {
270
      x = x - ((x >> 1) & 0x55555555);
271
      x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
272
      x = (x + (x >> 4)) & 0x0F0F0F0F;
273
      return (x * 0x01010101) >> 24;
274
0
   } else {
275
      // s < 4
276
0
      return ct_popcount(static_cast<uint32_t>(x));
277
0
   }
278
0
}
Unexecuted instantiation: _ZN5Botan11ct_popcountITkNSt3__117unsigned_integralEjEEhT_
Unexecuted instantiation: _ZN5Botan11ct_popcountITkNSt3__117unsigned_integralEmEEhT_
Unexecuted instantiation: _ZN5Botan11ct_popcountITkNSt3__117unsigned_integralEtEEhT_
Unexecuted instantiation: _ZN5Botan11ct_popcountITkNSt3__117unsigned_integralEhEEhT_
279
280
}  // namespace Botan
281
282
#endif