Coverage Report

Created: 2021-02-21 07:20

/src/botan/build/include/botan/internal/ct_utils.h
Line
Count
Source (jump to first uncovered line)
1
/*
2
* Functions for constant time operations on data and testing of
3
* constant time annotations using valgrind.
4
*
5
* For more information about constant time programming see
6
* Wagner, Molnar, et al "The Program Counter Security Model"
7
*
8
* (C) 2010 Falko Strenzke
9
* (C) 2015,2016,2018 Jack Lloyd
10
*
11
* Botan is released under the Simplified BSD License (see license.txt)
12
*/
13
14
#ifndef BOTAN_CT_UTILS_H_
15
#define BOTAN_CT_UTILS_H_
16
17
#include <botan/secmem.h>
18
#include <botan/internal/bit_ops.h>
19
#include <type_traits>
20
#include <vector>
21
22
#if defined(BOTAN_HAS_VALGRIND)
23
  #include <valgrind/memcheck.h>
24
#endif
25
26
namespace Botan {
27
28
namespace CT {
29
30
/**
31
* Use valgrind to mark the contents of memory as being undefined.
32
* Valgrind will accept operations which manipulate undefined values,
33
* but will warn if an undefined value is used to decided a conditional
34
* jump or a load/store address. So if we poison all of our inputs we
35
* can confirm that the operations in question are truly const time
36
* when compiled by whatever compiler is in use.
37
*
38
* Even better, the VALGRIND_MAKE_MEM_* macros work even when the
39
* program is not run under valgrind (though with a few cycles of
40
* overhead, which is unfortunate in final binaries as these
41
* annotations tend to be used in fairly important loops).
42
*
43
* This approach was first used in ctgrind (https://github.com/agl/ctgrind)
44
* but calling the valgrind mecheck API directly works just as well and
45
* doesn't require a custom patched valgrind.
46
*/
47
template<typename T>
48
inline void poison(const T* p, size_t n)
49
62.8k
   {
50
#if defined(BOTAN_HAS_VALGRIND)
51
   VALGRIND_MAKE_MEM_UNDEFINED(p, n * sizeof(T));
52
#else
53
62.8k
   BOTAN_UNUSED(p);
54
62.8k
   BOTAN_UNUSED(n);
55
62.8k
#endif
56
62.8k
   }
void Botan::CT::poison<unsigned char>(unsigned char const*, unsigned long)
Line
Count
Source
49
4.19k
   {
50
#if defined(BOTAN_HAS_VALGRIND)
51
   VALGRIND_MAKE_MEM_UNDEFINED(p, n * sizeof(T));
52
#else
53
4.19k
   BOTAN_UNUSED(p);
54
4.19k
   BOTAN_UNUSED(n);
55
4.19k
#endif
56
4.19k
   }
Unexecuted instantiation: void Botan::CT::poison<unsigned short>(unsigned short const*, unsigned long)
void Botan::CT::poison<unsigned long>(unsigned long const*, unsigned long)
Line
Count
Source
49
58.6k
   {
50
#if defined(BOTAN_HAS_VALGRIND)
51
   VALGRIND_MAKE_MEM_UNDEFINED(p, n * sizeof(T));
52
#else
53
58.6k
   BOTAN_UNUSED(p);
54
58.6k
   BOTAN_UNUSED(n);
55
58.6k
#endif
56
58.6k
   }
57
58
template<typename T>
59
inline void unpoison(const T* p, size_t n)
60
62.1k
   {
61
#if defined(BOTAN_HAS_VALGRIND)
62
   VALGRIND_MAKE_MEM_DEFINED(p, n * sizeof(T));
63
#else
64
62.1k
   BOTAN_UNUSED(p);
65
62.1k
   BOTAN_UNUSED(n);
66
62.1k
#endif
67
62.1k
   }
void Botan::CT::unpoison<unsigned char>(unsigned char const*, unsigned long)
Line
Count
Source
60
4.32k
   {
61
#if defined(BOTAN_HAS_VALGRIND)
62
   VALGRIND_MAKE_MEM_DEFINED(p, n * sizeof(T));
63
#else
64
4.32k
   BOTAN_UNUSED(p);
65
4.32k
   BOTAN_UNUSED(n);
66
4.32k
#endif
67
4.32k
   }
Unexecuted instantiation: void Botan::CT::unpoison<unsigned short>(unsigned short const*, unsigned long)
void Botan::CT::unpoison<unsigned long>(unsigned long const*, unsigned long)
Line
Count
Source
60
57.7k
   {
61
#if defined(BOTAN_HAS_VALGRIND)
62
   VALGRIND_MAKE_MEM_DEFINED(p, n * sizeof(T));
63
#else
64
57.7k
   BOTAN_UNUSED(p);
65
57.7k
   BOTAN_UNUSED(n);
66
57.7k
#endif
67
57.7k
   }
Unexecuted instantiation: void Botan::CT::unpoison<unsigned int>(unsigned int const*, unsigned long)
68
69
template<typename T>
70
inline void unpoison(T& p)
71
255M
   {
72
#if defined(BOTAN_HAS_VALGRIND)
73
   VALGRIND_MAKE_MEM_DEFINED(&p, sizeof(T));
74
#else
75
255M
   BOTAN_UNUSED(p);
76
255M
#endif
77
255M
   }
void Botan::CT::unpoison<unsigned long>(unsigned long&)
Line
Count
Source
71
151M
   {
72
#if defined(BOTAN_HAS_VALGRIND)
73
   VALGRIND_MAKE_MEM_DEFINED(&p, sizeof(T));
74
#else
75
151M
   BOTAN_UNUSED(p);
76
151M
#endif
77
151M
   }
void Botan::CT::unpoison<unsigned long const>(unsigned long const&)
Line
Count
Source
71
7.14M
   {
72
#if defined(BOTAN_HAS_VALGRIND)
73
   VALGRIND_MAKE_MEM_DEFINED(&p, sizeof(T));
74
#else
75
7.14M
   BOTAN_UNUSED(p);
76
7.14M
#endif
77
7.14M
   }
void Botan::CT::unpoison<unsigned int>(unsigned int&)
Line
Count
Source
71
689k
   {
72
#if defined(BOTAN_HAS_VALGRIND)
73
   VALGRIND_MAKE_MEM_DEFINED(&p, sizeof(T));
74
#else
75
689k
   BOTAN_UNUSED(p);
76
689k
#endif
77
689k
   }
void Botan::CT::unpoison<long>(long&)
Line
Count
Source
71
96.0M
   {
72
#if defined(BOTAN_HAS_VALGRIND)
73
   VALGRIND_MAKE_MEM_DEFINED(&p, sizeof(T));
74
#else
75
96.0M
   BOTAN_UNUSED(p);
76
96.0M
#endif
77
96.0M
   }
void Botan::CT::unpoison<unsigned char>(unsigned char&)
Line
Count
Source
71
115k
   {
72
#if defined(BOTAN_HAS_VALGRIND)
73
   VALGRIND_MAKE_MEM_DEFINED(&p, sizeof(T));
74
#else
75
115k
   BOTAN_UNUSED(p);
76
115k
#endif
77
115k
   }
Unexecuted instantiation: void Botan::CT::unpoison<Botan::CT::Mask<unsigned char> >(Botan::CT::Mask<unsigned char>&)
void Botan::CT::unpoison<unsigned char const>(unsigned char const&)
Line
Count
Source
71
858
   {
72
#if defined(BOTAN_HAS_VALGRIND)
73
   VALGRIND_MAKE_MEM_DEFINED(&p, sizeof(T));
74
#else
75
858
   BOTAN_UNUSED(p);
76
858
#endif
77
858
   }
void Botan::CT::unpoison<unsigned short>(unsigned short&)
Line
Count
Source
71
416
   {
72
#if defined(BOTAN_HAS_VALGRIND)
73
   VALGRIND_MAKE_MEM_DEFINED(&p, sizeof(T));
74
#else
75
416
   BOTAN_UNUSED(p);
76
416
#endif
77
416
   }
void Botan::CT::unpoison<Botan::CT::Mask<unsigned short> const>(Botan::CT::Mask<unsigned short> const&)
Line
Count
Source
71
208
   {
72
#if defined(BOTAN_HAS_VALGRIND)
73
   VALGRIND_MAKE_MEM_DEFINED(&p, sizeof(T));
74
#else
75
208
   BOTAN_UNUSED(p);
76
208
#endif
77
208
   }
78
79
/**
80
* A Mask type used for constant-time operations. A Mask<T> always has value
81
* either 0 (all bits cleared) or ~0 (all bits set). All operations in a Mask<T>
82
* are intended to compile to code which does not contain conditional jumps.
83
* This must be verified with tooling (eg binary disassembly or using valgrind)
84
* since you never know what a compiler might do.
85
*/
86
template<typename T>
87
class Mask
88
   {
89
   public:
90
      static_assert(std::is_unsigned<T>::value, "CT::Mask only defined for unsigned integer types");
91
92
      Mask(const Mask<T>& other) = default;
93
      Mask<T>& operator=(const Mask<T>& other) = default;
94
95
      /**
96
      * Derive a Mask from a Mask of a larger type
97
      */
98
      template<typename U>
99
      Mask(Mask<U> o) : m_mask(static_cast<T>(o.value()))
100
17.3k
         {
101
17.3k
         static_assert(sizeof(U) > sizeof(T), "sizes ok");
102
17.3k
         }
Unexecuted instantiation: Botan::CT::Mask<unsigned short>::Mask<unsigned int>(Botan::CT::Mask<unsigned int>)
Botan::CT::Mask<unsigned char>::Mask<unsigned long>(Botan::CT::Mask<unsigned long>)
Line
Count
Source
100
17.3k
         {
101
17.3k
         static_assert(sizeof(U) > sizeof(T), "sizes ok");
102
17.3k
         }
103
104
      /**
105
      * Return a Mask<T> with all bits set
106
      */
107
      static Mask<T> set()
108
173k
         {
109
173k
         return Mask<T>(static_cast<T>(~0));
110
173k
         }
Botan::CT::Mask<unsigned long>::set()
Line
Count
Source
108
57.7k
         {
109
57.7k
         return Mask<T>(static_cast<T>(~0));
110
57.7k
         }
Botan::CT::Mask<unsigned char>::set()
Line
Count
Source
108
115k
         {
109
115k
         return Mask<T>(static_cast<T>(~0));
110
115k
         }
111
112
      /**
113
      * Return a Mask<T> with all bits cleared
114
      */
115
      static Mask<T> cleared()
116
3.39M
         {
117
3.39M
         return Mask<T>(0);
118
3.39M
         }
Botan::CT::Mask<unsigned long>::cleared()
Line
Count
Source
116
3.39M
         {
117
3.39M
         return Mask<T>(0);
118
3.39M
         }
Botan::CT::Mask<unsigned char>::cleared()
Line
Count
Source
116
988
         {
117
988
         return Mask<T>(0);
118
988
         }
119
120
      /**
121
      * Return a Mask<T> which is set if v is != 0
122
      */
123
      static Mask<T> expand(T v)
124
1.25G
         {
125
1.25G
         return ~Mask<T>::is_zero(v);
126
1.25G
         }
Botan::CT::Mask<unsigned long>::expand(unsigned long)
Line
Count
Source
124
1.24G
         {
125
1.24G
         return ~Mask<T>::is_zero(v);
126
1.24G
         }
Botan::CT::Mask<unsigned char>::expand(unsigned char)
Line
Count
Source
124
15.9M
         {
125
15.9M
         return ~Mask<T>::is_zero(v);
126
15.9M
         }
Botan::CT::Mask<unsigned short>::expand(unsigned short)
Line
Count
Source
124
416
         {
125
416
         return ~Mask<T>::is_zero(v);
126
416
         }
127
128
      /**
129
      * Return a Mask<T> which is set if m is set
130
      */
131
      template<typename U>
132
      static Mask<T> expand(Mask<U> m)
133
213
         {
134
213
         static_assert(sizeof(U) < sizeof(T), "sizes ok");
135
213
         return ~Mask<T>::is_zero(m.value());
136
213
         }
137
138
      /**
139
      * Return a Mask<T> which is set if v is == 0 or cleared otherwise
140
      */
141
      static Mask<T> is_zero(T x)
142
4.15G
         {
143
4.15G
         return Mask<T>(ct_is_zero<T>(x));
144
4.15G
         }
Botan::CT::Mask<unsigned char>::is_zero(unsigned char)
Line
Count
Source
142
35.6M
         {
143
35.6M
         return Mask<T>(ct_is_zero<T>(x));
144
35.6M
         }
Botan::CT::Mask<unsigned long>::is_zero(unsigned long)
Line
Count
Source
142
4.12G
         {
143
4.12G
         return Mask<T>(ct_is_zero<T>(x));
144
4.12G
         }
Unexecuted instantiation: Botan::CT::Mask<unsigned int>::is_zero(unsigned int)
Botan::CT::Mask<unsigned short>::is_zero(unsigned short)
Line
Count
Source
142
63.1k
         {
143
63.1k
         return Mask<T>(ct_is_zero<T>(x));
144
63.1k
         }
145
146
      /**
147
      * Return a Mask<T> which is set if x == y
148
      */
149
      static Mask<T> is_equal(T x, T y)
150
2.86G
         {
151
2.86G
         return Mask<T>::is_zero(static_cast<T>(x ^ y));
152
2.86G
         }
Botan::CT::Mask<unsigned long>::is_equal(unsigned long, unsigned long)
Line
Count
Source
150
2.84G
         {
151
2.84G
         return Mask<T>::is_zero(static_cast<T>(x ^ y));
152
2.84G
         }
Botan::CT::Mask<unsigned char>::is_equal(unsigned char, unsigned char)
Line
Count
Source
150
19.1M
         {
151
19.1M
         return Mask<T>::is_zero(static_cast<T>(x ^ y));
152
19.1M
         }
Botan::CT::Mask<unsigned short>::is_equal(unsigned short, unsigned short)
Line
Count
Source
150
62.7k
         {
151
62.7k
         return Mask<T>::is_zero(static_cast<T>(x ^ y));
152
62.7k
         }
153
154
      /**
155
      * Return a Mask<T> which is set if x < y
156
      */
157
      static Mask<T> is_lt(T x, T y)
158
1.29G
         {
159
1.29G
         return Mask<T>(expand_top_bit<T>(x^((x^y) | ((x-y)^x))));
160
1.29G
         }
Botan::CT::Mask<unsigned long>::is_lt(unsigned long, unsigned long)
Line
Count
Source
158
1.29G
         {
159
1.29G
         return Mask<T>(expand_top_bit<T>(x^((x^y) | ((x-y)^x))));
160
1.29G
         }
Botan::CT::Mask<unsigned int>::is_lt(unsigned int, unsigned int)
Line
Count
Source
158
689k
         {
159
689k
         return Mask<T>(expand_top_bit<T>(x^((x^y) | ((x-y)^x))));
160
689k
         }
Botan::CT::Mask<unsigned char>::is_lt(unsigned char, unsigned char)
Line
Count
Source
158
1.42M
         {
159
1.42M
         return Mask<T>(expand_top_bit<T>(x^((x^y) | ((x-y)^x))));
160
1.42M
         }
Botan::CT::Mask<unsigned short>::is_lt(unsigned short, unsigned short)
Line
Count
Source
158
63.2k
         {
159
63.2k
         return Mask<T>(expand_top_bit<T>(x^((x^y) | ((x-y)^x))));
160
63.2k
         }
161
162
      /**
163
      * Return a Mask<T> which is set if x > y
164
      */
165
      static Mask<T> is_gt(T x, T y)
166
2.05M
         {
167
2.05M
         return Mask<T>::is_lt(y, x);
168
2.05M
         }
Botan::CT::Mask<unsigned long>::is_gt(unsigned long, unsigned long)
Line
Count
Source
166
1.99M
         {
167
1.99M
         return Mask<T>::is_lt(y, x);
168
1.99M
         }
Botan::CT::Mask<unsigned short>::is_gt(unsigned short, unsigned short)
Line
Count
Source
166
62.7k
         {
167
62.7k
         return Mask<T>::is_lt(y, x);
168
62.7k
         }
Botan::CT::Mask<unsigned char>::is_gt(unsigned char, unsigned char)
Line
Count
Source
166
157
         {
167
157
         return Mask<T>::is_lt(y, x);
168
157
         }
169
170
      /**
171
      * Return a Mask<T> which is set if x <= y
172
      */
173
      static Mask<T> is_lte(T x, T y)
174
2.04M
         {
175
2.04M
         return ~Mask<T>::is_gt(x, y);
176
2.04M
         }
Botan::CT::Mask<unsigned long>::is_lte(unsigned long, unsigned long)
Line
Count
Source
174
1.98M
         {
175
1.98M
         return ~Mask<T>::is_gt(x, y);
176
1.98M
         }
Botan::CT::Mask<unsigned short>::is_lte(unsigned short, unsigned short)
Line
Count
Source
174
62.7k
         {
175
62.7k
         return ~Mask<T>::is_gt(x, y);
176
62.7k
         }
177
178
      /**
179
      * Return a Mask<T> which is set if x >= y
180
      */
181
      static Mask<T> is_gte(T x, T y)
182
713k
         {
183
713k
         return ~Mask<T>::is_lt(x, y);
184
713k
         }
Botan::CT::Mask<unsigned int>::is_gte(unsigned int, unsigned int)
Line
Count
Source
182
689k
         {
183
689k
         return ~Mask<T>::is_lt(x, y);
184
689k
         }
Botan::CT::Mask<unsigned long>::is_gte(unsigned long, unsigned long)
Line
Count
Source
182
24.1k
         {
183
24.1k
         return ~Mask<T>::is_lt(x, y);
184
24.1k
         }
185
186
      static Mask<T> is_within_range(T v, T l, T u)
187
24.4M
         {
188
         //return Mask<T>::is_gte(v, l) & Mask<T>::is_lte(v, u);
189
190
24.4M
         const T v_lt_l = v^((v^l) | ((v-l)^v));
191
24.4M
         const T v_gt_u = u^((u^v) | ((u-v)^u));
192
24.4M
         const T either = v_lt_l | v_gt_u;
193
24.4M
         return ~Mask<T>(expand_top_bit(either));
194
24.4M
         }
195
196
      static Mask<T> is_any_of(T v, std::initializer_list<T> accepted)
197
8.13M
         {
198
8.13M
         T accept = 0;
199
200
8.13M
         for(auto a: accepted)
201
32.5M
            {
202
32.5M
            const T diff = a ^ v;
203
32.5M
            const T eq_zero = ~diff & (diff - 1);
204
32.5M
            accept |= eq_zero;
205
32.5M
            }
206
207
8.13M
         return Mask<T>(expand_top_bit(accept));
208
8.13M
         }
209
210
      /**
211
      * AND-combine two masks
212
      */
213
      Mask<T>& operator&=(Mask<T> o)
214
1.06M
         {
215
1.06M
         m_mask &= o.value();
216
1.06M
         return (*this);
217
1.06M
         }
Botan::CT::Mask<unsigned long>::operator&=(Botan::CT::Mask<unsigned long>)
Line
Count
Source
214
858k
         {
215
858k
         m_mask &= o.value();
216
858k
         return (*this);
217
858k
         }
Botan::CT::Mask<unsigned char>::operator&=(Botan::CT::Mask<unsigned char>)
Line
Count
Source
214
204k
         {
215
204k
         m_mask &= o.value();
216
204k
         return (*this);
217
204k
         }
218
219
      /**
220
      * XOR-combine two masks
221
      */
222
      Mask<T>& operator^=(Mask<T> o)
223
         {
224
         m_mask ^= o.value();
225
         return (*this);
226
         }
227
228
      /**
229
      * OR-combine two masks
230
      */
231
      Mask<T>& operator|=(Mask<T> o)
232
57.0M
         {
233
57.0M
         m_mask |= o.value();
234
57.0M
         return (*this);
235
57.0M
         }
Botan::CT::Mask<unsigned long>::operator|=(Botan::CT::Mask<unsigned long>)
Line
Count
Source
232
56.2M
         {
233
56.2M
         m_mask |= o.value();
234
56.2M
         return (*this);
235
56.2M
         }
Botan::CT::Mask<unsigned char>::operator|=(Botan::CT::Mask<unsigned char>)
Line
Count
Source
232
818k
         {
233
818k
         m_mask |= o.value();
234
818k
         return (*this);
235
818k
         }
Botan::CT::Mask<unsigned short>::operator|=(Botan::CT::Mask<unsigned short>)
Line
Count
Source
232
62.5k
         {
233
62.5k
         m_mask |= o.value();
234
62.5k
         return (*this);
235
62.5k
         }
236
237
      /**
238
      * AND-combine two masks
239
      */
240
      friend Mask<T> operator&(Mask<T> x, Mask<T> y)
241
125M
         {
242
125M
         return Mask<T>(x.value() & y.value());
243
125M
         }
Botan::CT::operator&(Botan::CT::Mask<unsigned long>, Botan::CT::Mask<unsigned long>)
Line
Count
Source
241
125M
         {
242
125M
         return Mask<T>(x.value() & y.value());
243
125M
         }
Botan::CT::operator&(Botan::CT::Mask<unsigned char>, Botan::CT::Mask<unsigned char>)
Line
Count
Source
241
609k
         {
242
609k
         return Mask<T>(x.value() & y.value());
243
609k
         }
Botan::CT::operator&(Botan::CT::Mask<unsigned short>, Botan::CT::Mask<unsigned short>)
Line
Count
Source
241
62.9k
         {
242
62.9k
         return Mask<T>(x.value() & y.value());
243
62.9k
         }
244
245
      /**
246
      * XOR-combine two masks
247
      */
248
      friend Mask<T> operator^(Mask<T> x, Mask<T> y)
249
240k
         {
250
240k
         return Mask<T>(x.value() ^ y.value());
251
240k
         }
252
253
      /**
254
      * OR-combine two masks
255
      */
256
      friend Mask<T> operator|(Mask<T> x, Mask<T> y)
257
125M
         {
258
125M
         return Mask<T>(x.value() | y.value());
259
125M
         }
Botan::CT::operator|(Botan::CT::Mask<unsigned long>, Botan::CT::Mask<unsigned long>)
Line
Count
Source
257
125M
         {
258
125M
         return Mask<T>(x.value() | y.value());
259
125M
         }
Botan::CT::operator|(Botan::CT::Mask<unsigned char>, Botan::CT::Mask<unsigned char>)
Line
Count
Source
257
204k
         {
258
204k
         return Mask<T>(x.value() | y.value());
259
204k
         }
260
261
      /**
262
      * Negate this mask
263
      */
264
      Mask<T> operator~() const
265
1.28G
         {
266
1.28G
         return Mask<T>(~value());
267
1.28G
         }
Botan::CT::Mask<unsigned long>::operator~() const
Line
Count
Source
265
1.24G
         {
266
1.24G
         return Mask<T>(~value());
267
1.24G
         }
Botan::CT::Mask<unsigned char>::operator~() const
Line
Count
Source
265
40.9M
         {
266
40.9M
         return Mask<T>(~value());
267
40.9M
         }
Botan::CT::Mask<unsigned int>::operator~() const
Line
Count
Source
265
689k
         {
266
689k
         return Mask<T>(~value());
267
689k
         }
Botan::CT::Mask<unsigned short>::operator~() const
Line
Count
Source
265
125k
         {
266
125k
         return Mask<T>(~value());
267
125k
         }
268
269
      /**
270
      * Return x if the mask is set, or otherwise zero
271
      */
272
      T if_set_return(T x) const
273
6.08G
         {
274
6.08G
         return m_mask & x;
275
6.08G
         }
Botan::CT::Mask<unsigned long>::if_set_return(unsigned long) const
Line
Count
Source
273
6.08G
         {
274
6.08G
         return m_mask & x;
275
6.08G
         }
Botan::CT::Mask<unsigned char>::if_set_return(unsigned char) const
Line
Count
Source
273
204k
         {
274
204k
         return m_mask & x;
275
204k
         }
Botan::CT::Mask<unsigned short>::if_set_return(unsigned short) const
Line
Count
Source
273
416
         {
274
416
         return m_mask & x;
275
416
         }
276
277
      /**
278
      * Return x if the mask is cleared, or otherwise zero
279
      */
280
      T if_not_set_return(T x) const
281
57.6M
         {
282
57.6M
         return ~m_mask & x;
283
57.6M
         }
Botan::CT::Mask<unsigned long>::if_not_set_return(unsigned long) const
Line
Count
Source
281
56.3M
         {
282
56.3M
         return ~m_mask & x;
283
56.3M
         }
Botan::CT::Mask<unsigned char>::if_not_set_return(unsigned char) const
Line
Count
Source
281
1.28M
         {
282
1.28M
         return ~m_mask & x;
283
1.28M
         }
Botan::CT::Mask<unsigned short>::if_not_set_return(unsigned short) const
Line
Count
Source
281
437
         {
282
437
         return ~m_mask & x;
283
437
         }
284
285
      /**
286
      * If this mask is set, return x, otherwise return y
287
      */
288
      T select(T x, T y) const
289
10.4G
         {
290
10.4G
         return choose(value(), x, y);
291
10.4G
         }
Botan::CT::Mask<unsigned long>::select(unsigned long, unsigned long) const
Line
Count
Source
289
10.3G
         {
290
10.3G
         return choose(value(), x, y);
291
10.3G
         }
Botan::CT::Mask<unsigned char>::select(unsigned char, unsigned char) const
Line
Count
Source
289
68.2M
         {
290
68.2M
         return choose(value(), x, y);
291
68.2M
         }
Botan::CT::Mask<unsigned int>::select(unsigned int, unsigned int) const
Line
Count
Source
289
689k
         {
290
689k
         return choose(value(), x, y);
291
689k
         }
Unexecuted instantiation: Botan::CT::Mask<unsigned short>::select(unsigned short, unsigned short) const
292
293
      T select_and_unpoison(T x, T y) const
294
684
         {
295
684
         T r = this->select(x, y);
296
684
         CT::unpoison(r);
297
684
         return r;
298
684
         }
Botan::CT::Mask<unsigned long>::select_and_unpoison(unsigned long, unsigned long) const
Line
Count
Source
294
527
         {
295
527
         T r = this->select(x, y);
296
527
         CT::unpoison(r);
297
527
         return r;
298
527
         }
Botan::CT::Mask<unsigned char>::select_and_unpoison(unsigned char, unsigned char) const
Line
Count
Source
294
157
         {
295
157
         T r = this->select(x, y);
296
157
         CT::unpoison(r);
297
157
         return r;
298
157
         }
299
300
      /**
301
      * If this mask is set, return x, otherwise return y
302
      */
303
      Mask<T> select_mask(Mask<T> x, Mask<T> y) const
304
934M
         {
305
934M
         return Mask<T>(select(x.value(), y.value()));
306
934M
         }
307
308
      /**
309
      * Conditionally set output to x or y, depending on if mask is set or
310
      * cleared (resp)
311
      */
312
      void select_n(T output[], const T x[], const T y[], size_t len) const
313
333M
         {
314
2.95G
         for(size_t i = 0; i != len; ++i)
315
2.62G
            output[i] = this->select(x[i], y[i]);
316
333M
         }
Botan::CT::Mask<unsigned long>::select_n(unsigned long*, unsigned long const*, unsigned long const*, unsigned long) const
Line
Count
Source
313
333M
         {
314
2.95G
         for(size_t i = 0; i != len; ++i)
315
2.62G
            output[i] = this->select(x[i], y[i]);
316
333M
         }
Unexecuted instantiation: Botan::CT::Mask<unsigned char>::select_n(unsigned char*, unsigned char const*, unsigned char const*, unsigned long) const
317
318
      /**
319
      * If this mask is set, zero out buf, otherwise do nothing
320
      */
321
      void if_set_zero_out(T buf[], size_t elems)
322
58.1k
         {
323
800k
         for(size_t i = 0; i != elems; ++i)
324
742k
            {
325
742k
            buf[i] = this->if_not_set_return(buf[i]);
326
742k
            }
327
58.1k
         }
Botan::CT::Mask<unsigned long>::if_set_zero_out(unsigned long*, unsigned long)
Line
Count
Source
322
57.7k
         {
323
375k
         for(size_t i = 0; i != elems; ++i)
324
317k
            {
325
317k
            buf[i] = this->if_not_set_return(buf[i]);
326
317k
            }
327
57.7k
         }
Botan::CT::Mask<unsigned char>::if_set_zero_out(unsigned char*, unsigned long)
Line
Count
Source
322
390
         {
323
425k
         for(size_t i = 0; i != elems; ++i)
324
425k
            {
325
425k
            buf[i] = this->if_not_set_return(buf[i]);
326
425k
            }
327
390
         }
328
329
      /**
330
      * Return the value of the mask, unpoisoned
331
      */
332
      T unpoisoned_value() const
333
11.8M
         {
334
11.8M
         T r = value();
335
11.8M
         CT::unpoison(r);
336
11.8M
         return r;
337
11.8M
         }
Botan::CT::Mask<unsigned long>::unpoisoned_value() const
Line
Count
Source
333
11.0M
         {
334
11.0M
         T r = value();
335
11.0M
         CT::unpoison(r);
336
11.0M
         return r;
337
11.0M
         }
Botan::CT::Mask<unsigned int>::unpoisoned_value() const
Line
Count
Source
333
689k
         {
334
689k
         T r = value();
335
689k
         CT::unpoison(r);
336
689k
         return r;
337
689k
         }
Botan::CT::Mask<unsigned char>::unpoisoned_value() const
Line
Count
Source
333
115k
         {
334
115k
         T r = value();
335
115k
         CT::unpoison(r);
336
115k
         return r;
337
115k
         }
Botan::CT::Mask<unsigned short>::unpoisoned_value() const
Line
Count
Source
333
208
         {
334
208
         T r = value();
335
208
         CT::unpoison(r);
336
208
         return r;
337
208
         }
338
339
      /**
340
      * Return true iff this mask is set
341
      */
342
      bool is_set() const
343
11.8M
         {
344
11.8M
         return unpoisoned_value() != 0;
345
11.8M
         }
Botan::CT::Mask<unsigned long>::is_set() const
Line
Count
Source
343
11.0M
         {
344
11.0M
         return unpoisoned_value() != 0;
345
11.0M
         }
Botan::CT::Mask<unsigned int>::is_set() const
Line
Count
Source
343
689k
         {
344
689k
         return unpoisoned_value() != 0;
345
689k
         }
Botan::CT::Mask<unsigned char>::is_set() const
Line
Count
Source
343
115k
         {
344
115k
         return unpoisoned_value() != 0;
345
115k
         }
Botan::CT::Mask<unsigned short>::is_set() const
Line
Count
Source
343
208
         {
344
208
         return unpoisoned_value() != 0;
345
208
         }
346
347
      /**
348
      * Return the underlying value of the mask
349
      */
350
      T value() const
351
14.3G
         {
352
14.3G
         return m_mask;
353
14.3G
         }
Botan::CT::Mask<unsigned char>::value() const
Line
Count
Source
351
111M
         {
352
111M
         return m_mask;
353
111M
         }
Botan::CT::Mask<unsigned long>::value() const
Line
Count
Source
351
14.1G
         {
352
14.1G
         return m_mask;
353
14.1G
         }
Botan::CT::Mask<unsigned int>::value() const
Line
Count
Source
351
2.06M
         {
352
2.06M
         return m_mask;
353
2.06M
         }
Botan::CT::Mask<unsigned short>::value() const
Line
Count
Source
351
314k
         {
352
314k
         return m_mask;
353
314k
         }
354
355
   private:
356
7.96G
      Mask(T m) : m_mask(m) {}
Botan::CT::Mask<unsigned char>::Mask(unsigned char)
Line
Count
Source
356
111M
      Mask(T m) : m_mask(m) {}
Botan::CT::Mask<unsigned long>::Mask(unsigned long)
Line
Count
Source
356
7.84G
      Mask(T m) : m_mask(m) {}
Botan::CT::Mask<unsigned int>::Mask(unsigned int)
Line
Count
Source
356
1.37M
      Mask(T m) : m_mask(m) {}
Botan::CT::Mask<unsigned short>::Mask(unsigned short)
Line
Count
Source
356
315k
      Mask(T m) : m_mask(m) {}
357
358
      T m_mask;
359
   };
360
361
template<typename T>
362
inline Mask<T> conditional_copy_mem(T cnd,
363
                                    T* to,
364
                                    const T* from0,
365
                                    const T* from1,
366
                                    size_t elems)
367
100M
   {
368
100M
   const auto mask = CT::Mask<T>::expand(cnd);
369
100M
   mask.select_n(to, from0, from1, elems);
370
100M
   return mask;
371
100M
   }
372
373
template<typename T>
374
inline void conditional_swap(bool cnd, T& x, T& y)
375
25.2M
   {
376
25.2M
   const auto swap = CT::Mask<T>::expand(cnd);
377
378
25.2M
   T t0 = swap.select(y, x);
379
25.2M
   T t1 = swap.select(x, y);
380
25.2M
   x = t0;
381
25.2M
   y = t1;
382
25.2M
   }
383
384
template<typename T>
385
inline void conditional_swap_ptr(bool cnd, T& x, T& y)
386
12.6M
   {
387
12.6M
   uintptr_t xp = reinterpret_cast<uintptr_t>(x);
388
12.6M
   uintptr_t yp = reinterpret_cast<uintptr_t>(y);
389
390
12.6M
   conditional_swap<uintptr_t>(cnd, xp, yp);
391
392
12.6M
   x = reinterpret_cast<T>(xp);
393
12.6M
   y = reinterpret_cast<T>(yp);
394
12.6M
   }
395
396
/**
397
* If bad_mask is unset, return in[delim_idx:input_length] copied to
398
* new buffer. If bad_mask is set, return an all zero vector of
399
* unspecified length.
400
*/
401
secure_vector<uint8_t> copy_output(CT::Mask<uint8_t> bad_input,
402
                                   const uint8_t input[],
403
                                   size_t input_length,
404
                                   size_t delim_idx);
405
406
secure_vector<uint8_t> strip_leading_zeros(const uint8_t in[], size_t length);
407
408
inline secure_vector<uint8_t> strip_leading_zeros(const secure_vector<uint8_t>& in)
409
0
   {
410
0
   return strip_leading_zeros(in.data(), in.size());
411
0
   }
412
413
}
414
415
}
416
417
#endif