Coverage Report

Created: 2020-08-01 06:18

/src/botan/build/include/botan/internal/ct_utils.h
Line
Count
Source
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
56.5k
   {
50
#if defined(BOTAN_HAS_VALGRIND)
51
   VALGRIND_MAKE_MEM_UNDEFINED(p, n * sizeof(T));
52
#else
53
56.5k
   BOTAN_UNUSED(p);
54
56.5k
   BOTAN_UNUSED(n);
55
56.5k
#endif
56
56.5k
   }
void Botan::CT::poison<unsigned long>(unsigned long const*, unsigned long)
Line
Count
Source
49
52.1k
   {
50
#if defined(BOTAN_HAS_VALGRIND)
51
   VALGRIND_MAKE_MEM_UNDEFINED(p, n * sizeof(T));
52
#else
53
52.1k
   BOTAN_UNUSED(p);
54
52.1k
   BOTAN_UNUSED(n);
55
52.1k
#endif
56
52.1k
   }
void Botan::CT::poison<unsigned char>(unsigned char const*, unsigned long)
Line
Count
Source
49
4.45k
   {
50
#if defined(BOTAN_HAS_VALGRIND)
51
   VALGRIND_MAKE_MEM_UNDEFINED(p, n * sizeof(T));
52
#else
53
4.45k
   BOTAN_UNUSED(p);
54
4.45k
   BOTAN_UNUSED(n);
55
4.45k
#endif
56
4.45k
   }
Unexecuted instantiation: void Botan::CT::poison<unsigned short>(unsigned short const*, unsigned long)
57
58
template<typename T>
59
inline void unpoison(const T* p, size_t n)
60
57.5k
   {
61
#if defined(BOTAN_HAS_VALGRIND)
62
   VALGRIND_MAKE_MEM_DEFINED(p, n * sizeof(T));
63
#else
64
57.5k
   BOTAN_UNUSED(p);
65
57.5k
   BOTAN_UNUSED(n);
66
57.5k
#endif
67
57.5k
   }
void Botan::CT::unpoison<unsigned long>(unsigned long const*, unsigned long)
Line
Count
Source
60
51.0k
   {
61
#if defined(BOTAN_HAS_VALGRIND)
62
   VALGRIND_MAKE_MEM_DEFINED(p, n * sizeof(T));
63
#else
64
51.0k
   BOTAN_UNUSED(p);
65
51.0k
   BOTAN_UNUSED(n);
66
51.0k
#endif
67
51.0k
   }
void Botan::CT::unpoison<unsigned char>(unsigned char const*, unsigned long)
Line
Count
Source
60
6.47k
   {
61
#if defined(BOTAN_HAS_VALGRIND)
62
   VALGRIND_MAKE_MEM_DEFINED(p, n * sizeof(T));
63
#else
64
6.47k
   BOTAN_UNUSED(p);
65
6.47k
   BOTAN_UNUSED(n);
66
6.47k
#endif
67
6.47k
   }
Unexecuted instantiation: void Botan::CT::unpoison<unsigned short>(unsigned short const*, unsigned long)
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
279M
   {
72
#if defined(BOTAN_HAS_VALGRIND)
73
   VALGRIND_MAKE_MEM_DEFINED(&p, sizeof(T));
74
#else
75
279M
   BOTAN_UNUSED(p);
76
279M
#endif
77
279M
   }
void Botan::CT::unpoison<unsigned long>(unsigned long&)
Line
Count
Source
71
169M
   {
72
#if defined(BOTAN_HAS_VALGRIND)
73
   VALGRIND_MAKE_MEM_DEFINED(&p, sizeof(T));
74
#else
75
169M
   BOTAN_UNUSED(p);
76
169M
#endif
77
169M
   }
void Botan::CT::unpoison<unsigned long const>(unsigned long const&)
Line
Count
Source
71
10.9M
   {
72
#if defined(BOTAN_HAS_VALGRIND)
73
   VALGRIND_MAKE_MEM_DEFINED(&p, sizeof(T));
74
#else
75
10.9M
   BOTAN_UNUSED(p);
76
10.9M
#endif
77
10.9M
   }
void Botan::CT::unpoison<unsigned int>(unsigned int&)
Line
Count
Source
71
683k
   {
72
#if defined(BOTAN_HAS_VALGRIND)
73
   VALGRIND_MAKE_MEM_DEFINED(&p, sizeof(T));
74
#else
75
683k
   BOTAN_UNUSED(p);
76
683k
#endif
77
683k
   }
void Botan::CT::unpoison<long>(long&)
Line
Count
Source
71
98.3M
   {
72
#if defined(BOTAN_HAS_VALGRIND)
73
   VALGRIND_MAKE_MEM_DEFINED(&p, sizeof(T));
74
#else
75
98.3M
   BOTAN_UNUSED(p);
76
98.3M
#endif
77
98.3M
   }
Unexecuted instantiation: void Botan::CT::unpoison<Botan::CT::Mask<unsigned char> >(Botan::CT::Mask<unsigned char>&)
void Botan::CT::unpoison<unsigned char>(unsigned char&)
Line
Count
Source
71
542
   {
72
#if defined(BOTAN_HAS_VALGRIND)
73
   VALGRIND_MAKE_MEM_DEFINED(&p, sizeof(T));
74
#else
75
542
   BOTAN_UNUSED(p);
76
542
#endif
77
542
   }
void Botan::CT::unpoison<unsigned char const>(unsigned char const&)
Line
Count
Source
71
1.11k
   {
72
#if defined(BOTAN_HAS_VALGRIND)
73
   VALGRIND_MAKE_MEM_DEFINED(&p, sizeof(T));
74
#else
75
1.11k
   BOTAN_UNUSED(p);
76
1.11k
#endif
77
1.11k
   }
void Botan::CT::unpoison<unsigned short>(unsigned short&)
Line
Count
Source
71
552
   {
72
#if defined(BOTAN_HAS_VALGRIND)
73
   VALGRIND_MAKE_MEM_DEFINED(&p, sizeof(T));
74
#else
75
552
   BOTAN_UNUSED(p);
76
552
#endif
77
552
   }
void Botan::CT::unpoison<Botan::CT::Mask<unsigned short> const>(Botan::CT::Mask<unsigned short> const&)
Line
Count
Source
71
276
   {
72
#if defined(BOTAN_HAS_VALGRIND)
73
   VALGRIND_MAKE_MEM_DEFINED(&p, sizeof(T));
74
#else
75
276
   BOTAN_UNUSED(p);
76
276
#endif
77
276
   }
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
20.3k
         {
101
20.3k
         static_assert(sizeof(U) > sizeof(T), "sizes ok");
102
20.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
20.3k
         {
101
20.3k
         static_assert(sizeof(U) > sizeof(T), "sizes ok");
102
20.3k
         }
103
104
      /**
105
      * Return a Mask<T> with all bits set
106
      */
107
      static Mask<T> set()
108
53.5k
         {
109
53.5k
         return Mask<T>(static_cast<T>(~0));
110
53.5k
         }
Botan::CT::Mask<unsigned long>::set()
Line
Count
Source
108
51.0k
         {
109
51.0k
         return Mask<T>(static_cast<T>(~0));
110
51.0k
         }
Botan::CT::Mask<unsigned char>::set()
Line
Count
Source
108
2.51k
         {
109
2.51k
         return Mask<T>(static_cast<T>(~0));
110
2.51k
         }
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
3.29k
         {
117
3.29k
         return Mask<T>(0);
118
3.29k
         }
119
120
      /**
121
      * Return a Mask<T> which is set if v is != 0
122
      */
123
      static Mask<T> expand(T v)
124
1.47G
         {
125
1.47G
         return ~Mask<T>::is_zero(v);
126
1.47G
         }
Botan::CT::Mask<unsigned long>::expand(unsigned long)
Line
Count
Source
124
1.46G
         {
125
1.46G
         return ~Mask<T>::is_zero(v);
126
1.46G
         }
Botan::CT::Mask<unsigned char>::expand(unsigned char)
Line
Count
Source
124
19.2M
         {
125
19.2M
         return ~Mask<T>::is_zero(v);
126
19.2M
         }
Botan::CT::Mask<unsigned short>::expand(unsigned short)
Line
Count
Source
124
552
         {
125
552
         return ~Mask<T>::is_zero(v);
126
552
         }
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
212
         {
134
212
         static_assert(sizeof(U) < sizeof(T), "sizes ok");
135
212
         return ~Mask<T>::is_zero(m.value());
136
212
         }
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.60G
         {
143
4.60G
         return Mask<T>(ct_is_zero<T>(x));
144
4.60G
         }
Botan::CT::Mask<unsigned long>::is_zero(unsigned long)
Line
Count
Source
142
4.57G
         {
143
4.57G
         return Mask<T>(ct_is_zero<T>(x));
144
4.57G
         }
Botan::CT::Mask<unsigned char>::is_zero(unsigned char)
Line
Count
Source
142
20.8M
         {
143
20.8M
         return Mask<T>(ct_is_zero<T>(x));
144
20.8M
         }
Unexecuted instantiation: Botan::CT::Mask<unsigned int>::is_zero(unsigned int)
Botan::CT::Mask<unsigned short>::is_zero(unsigned short)
Line
Count
Source
142
77.8k
         {
143
77.8k
         return Mask<T>(ct_is_zero<T>(x));
144
77.8k
         }
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
3.07G
         {
151
3.07G
         return Mask<T>::is_zero(static_cast<T>(x ^ y));
152
3.07G
         }
Botan::CT::Mask<unsigned long>::is_equal(unsigned long, unsigned long)
Line
Count
Source
150
3.07G
         {
151
3.07G
         return Mask<T>::is_zero(static_cast<T>(x ^ y));
152
3.07G
         }
Botan::CT::Mask<unsigned char>::is_equal(unsigned char, unsigned char)
Line
Count
Source
150
387k
         {
151
387k
         return Mask<T>::is_zero(static_cast<T>(x ^ y));
152
387k
         }
Botan::CT::Mask<unsigned short>::is_equal(unsigned short, unsigned short)
Line
Count
Source
150
77.3k
         {
151
77.3k
         return Mask<T>::is_zero(static_cast<T>(x ^ y));
152
77.3k
         }
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.39G
         {
159
1.39G
         return Mask<T>(expand_top_bit<T>(x^((x^y) | ((x-y)^x))));
160
1.39G
         }
Botan::CT::Mask<unsigned long>::is_lt(unsigned long, unsigned long)
Line
Count
Source
158
1.39G
         {
159
1.39G
         return Mask<T>(expand_top_bit<T>(x^((x^y) | ((x-y)^x))));
160
1.39G
         }
Botan::CT::Mask<unsigned int>::is_lt(unsigned int, unsigned int)
Line
Count
Source
158
683k
         {
159
683k
         return Mask<T>(expand_top_bit<T>(x^((x^y) | ((x-y)^x))));
160
683k
         }
Botan::CT::Mask<unsigned short>::is_lt(unsigned short, unsigned short)
Line
Count
Source
158
77.8k
         {
159
77.8k
         return Mask<T>(expand_top_bit<T>(x^((x^y) | ((x-y)^x))));
160
77.8k
         }
Botan::CT::Mask<unsigned char>::is_lt(unsigned char, unsigned char)
Line
Count
Source
158
155
         {
159
155
         return Mask<T>(expand_top_bit<T>(x^((x^y) | ((x-y)^x))));
160
155
         }
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.66M
         {
167
2.66M
         return Mask<T>::is_lt(y, x);
168
2.66M
         }
Botan::CT::Mask<unsigned long>::is_gt(unsigned long, unsigned long)
Line
Count
Source
166
2.58M
         {
167
2.58M
         return Mask<T>::is_lt(y, x);
168
2.58M
         }
Botan::CT::Mask<unsigned short>::is_gt(unsigned short, unsigned short)
Line
Count
Source
166
77.3k
         {
167
77.3k
         return Mask<T>::is_lt(y, x);
168
77.3k
         }
Botan::CT::Mask<unsigned char>::is_gt(unsigned char, unsigned char)
Line
Count
Source
166
155
         {
167
155
         return Mask<T>::is_lt(y, x);
168
155
         }
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.65M
         {
175
2.65M
         return ~Mask<T>::is_gt(x, y);
176
2.65M
         }
Botan::CT::Mask<unsigned long>::is_lte(unsigned long, unsigned long)
Line
Count
Source
174
2.57M
         {
175
2.57M
         return ~Mask<T>::is_gt(x, y);
176
2.57M
         }
Botan::CT::Mask<unsigned short>::is_lte(unsigned short, unsigned short)
Line
Count
Source
174
77.3k
         {
175
77.3k
         return ~Mask<T>::is_gt(x, y);
176
77.3k
         }
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
710k
         {
183
710k
         return ~Mask<T>::is_lt(x, y);
184
710k
         }
Botan::CT::Mask<unsigned int>::is_gte(unsigned int, unsigned int)
Line
Count
Source
182
683k
         {
183
683k
         return ~Mask<T>::is_lt(x, y);
184
683k
         }
Botan::CT::Mask<unsigned long>::is_gte(unsigned long, unsigned long)
Line
Count
Source
182
27.0k
         {
183
27.0k
         return ~Mask<T>::is_lt(x, y);
184
27.0k
         }
185
186
      /**
187
      * AND-combine two masks
188
      */
189
      Mask<T>& operator&=(Mask<T> o)
190
1.71M
         {
191
1.71M
         m_mask &= o.value();
192
1.71M
         return (*this);
193
1.71M
         }
Botan::CT::Mask<unsigned long>::operator&=(Botan::CT::Mask<unsigned long>)
Line
Count
Source
190
915k
         {
191
915k
         m_mask &= o.value();
192
915k
         return (*this);
193
915k
         }
Botan::CT::Mask<unsigned char>::operator&=(Botan::CT::Mask<unsigned char>)
Line
Count
Source
190
794k
         {
191
794k
         m_mask &= o.value();
192
794k
         return (*this);
193
794k
         }
194
195
      /**
196
      * XOR-combine two masks
197
      */
198
      Mask<T>& operator^=(Mask<T> o)
199
         {
200
         m_mask ^= o.value();
201
         return (*this);
202
         }
203
204
      /**
205
      * OR-combine two masks
206
      */
207
      Mask<T>& operator|=(Mask<T> o)
208
58.5M
         {
209
58.5M
         m_mask |= o.value();
210
58.5M
         return (*this);
211
58.5M
         }
Botan::CT::Mask<unsigned long>::operator|=(Botan::CT::Mask<unsigned long>)
Line
Count
Source
208
57.6M
         {
209
57.6M
         m_mask |= o.value();
210
57.6M
         return (*this);
211
57.6M
         }
Botan::CT::Mask<unsigned char>::operator|=(Botan::CT::Mask<unsigned char>)
Line
Count
Source
208
790k
         {
209
790k
         m_mask |= o.value();
210
790k
         return (*this);
211
790k
         }
Botan::CT::Mask<unsigned short>::operator|=(Botan::CT::Mask<unsigned short>)
Line
Count
Source
208
77.0k
         {
209
77.0k
         m_mask |= o.value();
210
77.0k
         return (*this);
211
77.0k
         }
212
213
      /**
214
      * AND-combine two masks
215
      */
216
      friend Mask<T> operator&(Mask<T> x, Mask<T> y)
217
149M
         {
218
149M
         return Mask<T>(x.value() & y.value());
219
149M
         }
Botan::CT::operator&(Botan::CT::Mask<unsigned long>, Botan::CT::Mask<unsigned long>)
Line
Count
Source
217
149M
         {
218
149M
         return Mask<T>(x.value() & y.value());
219
149M
         }
Botan::CT::operator&(Botan::CT::Mask<unsigned char>, Botan::CT::Mask<unsigned char>)
Line
Count
Source
217
581k
         {
218
581k
         return Mask<T>(x.value() & y.value());
219
581k
         }
Botan::CT::operator&(Botan::CT::Mask<unsigned short>, Botan::CT::Mask<unsigned short>)
Line
Count
Source
217
77.6k
         {
218
77.6k
         return Mask<T>(x.value() & y.value());
219
77.6k
         }
220
221
      /**
222
      * XOR-combine two masks
223
      */
224
      friend Mask<T> operator^(Mask<T> x, Mask<T> y)
225
2.22M
         {
226
2.22M
         return Mask<T>(x.value() ^ y.value());
227
2.22M
         }
228
229
      /**
230
      * OR-combine two masks
231
      */
232
      friend Mask<T> operator|(Mask<T> x, Mask<T> y)
233
149M
         {
234
149M
         return Mask<T>(x.value() | y.value());
235
149M
         }
Botan::CT::operator|(Botan::CT::Mask<unsigned long>, Botan::CT::Mask<unsigned long>)
Line
Count
Source
233
149M
         {
234
149M
         return Mask<T>(x.value() | y.value());
235
149M
         }
Botan::CT::operator|(Botan::CT::Mask<unsigned char>, Botan::CT::Mask<unsigned char>)
Line
Count
Source
233
194k
         {
234
194k
         return Mask<T>(x.value() | y.value());
235
194k
         }
236
237
      /**
238
      * Negate this mask
239
      */
240
      Mask<T> operator~() const
241
1.48G
         {
242
1.48G
         return Mask<T>(~value());
243
1.48G
         }
Botan::CT::Mask<unsigned long>::operator~() const
Line
Count
Source
241
1.46G
         {
242
1.46G
         return Mask<T>(~value());
243
1.46G
         }
Botan::CT::Mask<unsigned char>::operator~() const
Line
Count
Source
241
19.8M
         {
242
19.8M
         return Mask<T>(~value());
243
19.8M
         }
Botan::CT::Mask<unsigned int>::operator~() const
Line
Count
Source
241
683k
         {
242
683k
         return Mask<T>(~value());
243
683k
         }
Botan::CT::Mask<unsigned short>::operator~() const
Line
Count
Source
241
154k
         {
242
154k
         return Mask<T>(~value());
243
154k
         }
244
245
      /**
246
      * Return x if the mask is set, or otherwise zero
247
      */
248
      T if_set_return(T x) const
249
7.98G
         {
250
7.98G
         return m_mask & x;
251
7.98G
         }
Botan::CT::Mask<unsigned long>::if_set_return(unsigned long) const
Line
Count
Source
249
7.98G
         {
250
7.98G
         return m_mask & x;
251
7.98G
         }
Botan::CT::Mask<unsigned char>::if_set_return(unsigned char) const
Line
Count
Source
249
794k
         {
250
794k
         return m_mask & x;
251
794k
         }
Botan::CT::Mask<unsigned short>::if_set_return(unsigned short) const
Line
Count
Source
249
552
         {
250
552
         return m_mask & x;
251
552
         }
252
253
      /**
254
      * Return x if the mask is cleared, or otherwise zero
255
      */
256
      T if_not_set_return(T x) const
257
59.2M
         {
258
59.2M
         return ~m_mask & x;
259
59.2M
         }
Botan::CT::Mask<unsigned long>::if_not_set_return(unsigned long) const
Line
Count
Source
257
57.8M
         {
258
57.8M
         return ~m_mask & x;
259
57.8M
         }
Botan::CT::Mask<unsigned char>::if_not_set_return(unsigned char) const
Line
Count
Source
257
1.41M
         {
258
1.41M
         return ~m_mask & x;
259
1.41M
         }
Botan::CT::Mask<unsigned short>::if_not_set_return(unsigned short) const
Line
Count
Source
257
504
         {
258
504
         return ~m_mask & x;
259
504
         }
260
261
      /**
262
      * If this mask is set, return x, otherwise return y
263
      */
264
      T select(T x, T y) const
265
24.3G
         {
266
24.3G
         // (x & value()) | (y & ~value())
267
24.3G
         return static_cast<T>(y ^ (value() & (x ^ y)));
268
24.3G
         }
Botan::CT::Mask<unsigned long>::select(unsigned long, unsigned long) const
Line
Count
Source
265
24.3G
         {
266
24.3G
         // (x & value()) | (y & ~value())
267
24.3G
         return static_cast<T>(y ^ (value() & (x ^ y)));
268
24.3G
         }
Botan::CT::Mask<unsigned char>::select(unsigned char, unsigned char) const
Line
Count
Source
265
19.2M
         {
266
19.2M
         // (x & value()) | (y & ~value())
267
19.2M
         return static_cast<T>(y ^ (value() & (x ^ y)));
268
19.2M
         }
Botan::CT::Mask<unsigned int>::select(unsigned int, unsigned int) const
Line
Count
Source
265
683k
         {
266
683k
         // (x & value()) | (y & ~value())
267
683k
         return static_cast<T>(y ^ (value() & (x ^ y)));
268
683k
         }
Unexecuted instantiation: Botan::CT::Mask<unsigned short>::select(unsigned short, unsigned short) const
269
270
      T select_and_unpoison(T x, T y) const
271
677
         {
272
677
         T r = this->select(x, y);
273
677
         CT::unpoison(r);
274
677
         return r;
275
677
         }
Botan::CT::Mask<unsigned long>::select_and_unpoison(unsigned long, unsigned long) const
Line
Count
Source
271
522
         {
272
522
         T r = this->select(x, y);
273
522
         CT::unpoison(r);
274
522
         return r;
275
522
         }
Botan::CT::Mask<unsigned char>::select_and_unpoison(unsigned char, unsigned char) const
Line
Count
Source
271
155
         {
272
155
         T r = this->select(x, y);
273
155
         CT::unpoison(r);
274
155
         return r;
275
155
         }
276
277
      /**
278
      * If this mask is set, return x, otherwise return y
279
      */
280
      Mask<T> select_mask(Mask<T> x, Mask<T> y) const
281
985M
         {
282
985M
         return Mask<T>(select(x.value(), y.value()));
283
985M
         }
284
285
      /**
286
      * Conditionally set output to x or y, depending on if mask is set or
287
      * cleared (resp)
288
      */
289
      void select_n(T output[], const T x[], const T y[], size_t len) const
290
545M
         {
291
5.18G
         for(size_t i = 0; i != len; ++i)
292
4.64G
            output[i] = this->select(x[i], y[i]);
293
545M
         }
Botan::CT::Mask<unsigned long>::select_n(unsigned long*, unsigned long const*, unsigned long const*, unsigned long) const
Line
Count
Source
290
545M
         {
291
5.18G
         for(size_t i = 0; i != len; ++i)
292
4.64G
            output[i] = this->select(x[i], y[i]);
293
545M
         }
Unexecuted instantiation: Botan::CT::Mask<unsigned char>::select_n(unsigned char*, unsigned char const*, unsigned char const*, unsigned long) const
294
295
      /**
296
      * If this mask is set, zero out buf, otherwise do nothing
297
      */
298
      void if_set_zero_out(T buf[], size_t elems)
299
53.7k
         {
300
1.40M
         for(size_t i = 0; i != elems; ++i)
301
1.35M
            {
302
1.35M
            buf[i] = this->if_not_set_return(buf[i]);
303
1.35M
            }
304
53.7k
         }
Botan::CT::Mask<unsigned long>::if_set_zero_out(unsigned long*, unsigned long)
Line
Count
Source
299
51.0k
         {
300
393k
         for(size_t i = 0; i != elems; ++i)
301
342k
            {
302
342k
            buf[i] = this->if_not_set_return(buf[i]);
303
342k
            }
304
51.0k
         }
Botan::CT::Mask<unsigned char>::if_set_zero_out(unsigned char*, unsigned long)
Line
Count
Source
299
2.69k
         {
300
1.01M
         for(size_t i = 0; i != elems; ++i)
301
1.01M
            {
302
1.01M
            buf[i] = this->if_not_set_return(buf[i]);
303
1.01M
            }
304
2.69k
         }
305
306
      /**
307
      * Return the value of the mask, unpoisoned
308
      */
309
      T unpoisoned_value() const
310
12.3M
         {
311
12.3M
         T r = value();
312
12.3M
         CT::unpoison(r);
313
12.3M
         return r;
314
12.3M
         }
Botan::CT::Mask<unsigned long>::unpoisoned_value() const
Line
Count
Source
310
11.7M
         {
311
11.7M
         T r = value();
312
11.7M
         CT::unpoison(r);
313
11.7M
         return r;
314
11.7M
         }
Botan::CT::Mask<unsigned int>::unpoisoned_value() const
Line
Count
Source
310
683k
         {
311
683k
         T r = value();
312
683k
         CT::unpoison(r);
313
683k
         return r;
314
683k
         }
Botan::CT::Mask<unsigned char>::unpoisoned_value() const
Line
Count
Source
310
387
         {
311
387
         T r = value();
312
387
         CT::unpoison(r);
313
387
         return r;
314
387
         }
Botan::CT::Mask<unsigned short>::unpoisoned_value() const
Line
Count
Source
310
276
         {
311
276
         T r = value();
312
276
         CT::unpoison(r);
313
276
         return r;
314
276
         }
315
316
      /**
317
      * Return true iff this mask is set
318
      */
319
      bool is_set() const
320
12.3M
         {
321
12.3M
         return unpoisoned_value() != 0;
322
12.3M
         }
Botan::CT::Mask<unsigned long>::is_set() const
Line
Count
Source
320
11.7M
         {
321
11.7M
         return unpoisoned_value() != 0;
322
11.7M
         }
Botan::CT::Mask<unsigned int>::is_set() const
Line
Count
Source
320
683k
         {
321
683k
         return unpoisoned_value() != 0;
322
683k
         }
Unexecuted instantiation: Botan::CT::Mask<unsigned char>::is_set() const
Botan::CT::Mask<unsigned short>::is_set() const
Line
Count
Source
320
276
         {
321
276
         return unpoisoned_value() != 0;
322
276
         }
323
324
      /**
325
      * Return the underlying value of the mask
326
      */
327
      T value() const
328
28.6G
         {
329
28.6G
         return m_mask;
330
28.6G
         }
Botan::CT::Mask<unsigned long>::value() const
Line
Count
Source
328
28.6G
         {
329
28.6G
         return m_mask;
330
28.6G
         }
Botan::CT::Mask<unsigned char>::value() const
Line
Count
Source
328
42.1M
         {
329
42.1M
         return m_mask;
330
42.1M
         }
Botan::CT::Mask<unsigned int>::value() const
Line
Count
Source
328
2.04M
         {
329
2.04M
         return m_mask;
330
2.04M
         }
Botan::CT::Mask<unsigned short>::value() const
Line
Count
Source
328
387k
         {
329
387k
         return m_mask;
330
387k
         }
331
332
   private:
333
8.76G
      Mask(T m) : m_mask(m) {}
Botan::CT::Mask<unsigned long>::Mask(unsigned long)
Line
Count
Source
333
8.72G
      Mask(T m) : m_mask(m) {}
Botan::CT::Mask<unsigned char>::Mask(unsigned char)
Line
Count
Source
333
41.4M
      Mask(T m) : m_mask(m) {}
Botan::CT::Mask<unsigned int>::Mask(unsigned int)
Line
Count
Source
333
1.36M
      Mask(T m) : m_mask(m) {}
Botan::CT::Mask<unsigned short>::Mask(unsigned short)
Line
Count
Source
333
388k
      Mask(T m) : m_mask(m) {}
334
335
      T m_mask;
336
   };
337
338
template<typename T>
339
inline Mask<T> conditional_copy_mem(T cnd,
340
                                    T* to,
341
                                    const T* from0,
342
                                    const T* from1,
343
                                    size_t elems)
344
94.9M
   {
345
94.9M
   const auto mask = CT::Mask<T>::expand(cnd);
346
94.9M
   mask.select_n(to, from0, from1, elems);
347
94.9M
   return mask;
348
94.9M
   }
349
350
template<typename T>
351
inline void conditional_swap(bool cnd, T& x, T& y)
352
29.7M
   {
353
29.7M
   const auto swap = CT::Mask<T>::expand(cnd);
354
29.7M
355
29.7M
   T t0 = swap.select(y, x);
356
29.7M
   T t1 = swap.select(x, y);
357
29.7M
   x = t0;
358
29.7M
   y = t1;
359
29.7M
   }
360
361
template<typename T>
362
inline void conditional_swap_ptr(bool cnd, T& x, T& y)
363
14.8M
   {
364
14.8M
   uintptr_t xp = reinterpret_cast<uintptr_t>(x);
365
14.8M
   uintptr_t yp = reinterpret_cast<uintptr_t>(y);
366
14.8M
367
14.8M
   conditional_swap<uintptr_t>(cnd, xp, yp);
368
14.8M
369
14.8M
   x = reinterpret_cast<T>(xp);
370
14.8M
   y = reinterpret_cast<T>(yp);
371
14.8M
   }
372
373
/**
374
* If bad_mask is unset, return in[delim_idx:input_length] copied to
375
* new buffer. If bad_mask is set, return an all zero vector of
376
* unspecified length.
377
*/
378
secure_vector<uint8_t> copy_output(CT::Mask<uint8_t> bad_input,
379
                                   const uint8_t input[],
380
                                   size_t input_length,
381
                                   size_t delim_idx);
382
383
secure_vector<uint8_t> strip_leading_zeros(const uint8_t in[], size_t length);
384
385
inline secure_vector<uint8_t> strip_leading_zeros(const secure_vector<uint8_t>& in)
386
2.30k
   {
387
2.30k
   return strip_leading_zeros(in.data(), in.size());
388
2.30k
   }
389
390
}
391
392
}
393
394
#endif