Coverage Report

Created: 2021-05-04 09:02

/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.5k
   {
50
#if defined(BOTAN_HAS_VALGRIND)
51
   VALGRIND_MAKE_MEM_UNDEFINED(p, n * sizeof(T));
52
#else
53
62.5k
   BOTAN_UNUSED(p, n);
54
62.5k
#endif
55
62.5k
   }
void Botan::CT::poison<unsigned char>(unsigned char const*, unsigned long)
Line
Count
Source
49
2.88k
   {
50
#if defined(BOTAN_HAS_VALGRIND)
51
   VALGRIND_MAKE_MEM_UNDEFINED(p, n * sizeof(T));
52
#else
53
2.88k
   BOTAN_UNUSED(p, n);
54
2.88k
#endif
55
2.88k
   }
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
59.6k
   {
50
#if defined(BOTAN_HAS_VALGRIND)
51
   VALGRIND_MAKE_MEM_UNDEFINED(p, n * sizeof(T));
52
#else
53
59.6k
   BOTAN_UNUSED(p, n);
54
59.6k
#endif
55
59.6k
   }
Unexecuted instantiation: void Botan::CT::poison<unsigned int>(unsigned int const*, unsigned long)
56
57
template<typename T>
58
inline void unpoison(const T* p, size_t n)
59
62.3k
   {
60
#if defined(BOTAN_HAS_VALGRIND)
61
   VALGRIND_MAKE_MEM_DEFINED(p, n * sizeof(T));
62
#else
63
62.3k
   BOTAN_UNUSED(p, n);
64
62.3k
#endif
65
62.3k
   }
void Botan::CT::unpoison<unsigned char>(unsigned char const*, unsigned long)
Line
Count
Source
59
3.40k
   {
60
#if defined(BOTAN_HAS_VALGRIND)
61
   VALGRIND_MAKE_MEM_DEFINED(p, n * sizeof(T));
62
#else
63
3.40k
   BOTAN_UNUSED(p, n);
64
3.40k
#endif
65
3.40k
   }
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
59
58.9k
   {
60
#if defined(BOTAN_HAS_VALGRIND)
61
   VALGRIND_MAKE_MEM_DEFINED(p, n * sizeof(T));
62
#else
63
58.9k
   BOTAN_UNUSED(p, n);
64
58.9k
#endif
65
58.9k
   }
Unexecuted instantiation: void Botan::CT::unpoison<unsigned int>(unsigned int const*, unsigned long)
66
67
template<typename T>
68
inline void unpoison(T& p)
69
260M
   {
70
#if defined(BOTAN_HAS_VALGRIND)
71
   VALGRIND_MAKE_MEM_DEFINED(&p, sizeof(T));
72
#else
73
260M
   BOTAN_UNUSED(p);
74
260M
#endif
75
260M
   }
void Botan::CT::unpoison<unsigned long>(unsigned long&)
Line
Count
Source
69
156M
   {
70
#if defined(BOTAN_HAS_VALGRIND)
71
   VALGRIND_MAKE_MEM_DEFINED(&p, sizeof(T));
72
#else
73
156M
   BOTAN_UNUSED(p);
74
156M
#endif
75
156M
   }
void Botan::CT::unpoison<unsigned long const>(unsigned long const&)
Line
Count
Source
69
7.55M
   {
70
#if defined(BOTAN_HAS_VALGRIND)
71
   VALGRIND_MAKE_MEM_DEFINED(&p, sizeof(T));
72
#else
73
7.55M
   BOTAN_UNUSED(p);
74
7.55M
#endif
75
7.55M
   }
void Botan::CT::unpoison<unsigned int>(unsigned int&)
Line
Count
Source
69
712k
   {
70
#if defined(BOTAN_HAS_VALGRIND)
71
   VALGRIND_MAKE_MEM_DEFINED(&p, sizeof(T));
72
#else
73
712k
   BOTAN_UNUSED(p);
74
712k
#endif
75
712k
   }
void Botan::CT::unpoison<long>(long&)
Line
Count
Source
69
95.3M
   {
70
#if defined(BOTAN_HAS_VALGRIND)
71
   VALGRIND_MAKE_MEM_DEFINED(&p, sizeof(T));
72
#else
73
95.3M
   BOTAN_UNUSED(p);
74
95.3M
#endif
75
95.3M
   }
void Botan::CT::unpoison<unsigned char>(unsigned char&)
Line
Count
Source
69
113k
   {
70
#if defined(BOTAN_HAS_VALGRIND)
71
   VALGRIND_MAKE_MEM_DEFINED(&p, sizeof(T));
72
#else
73
113k
   BOTAN_UNUSED(p);
74
113k
#endif
75
113k
   }
void Botan::CT::unpoison<unsigned char const>(unsigned char const&)
Line
Count
Source
69
362
   {
70
#if defined(BOTAN_HAS_VALGRIND)
71
   VALGRIND_MAKE_MEM_DEFINED(&p, sizeof(T));
72
#else
73
362
   BOTAN_UNUSED(p);
74
362
#endif
75
362
   }
void Botan::CT::unpoison<unsigned short>(unsigned short&)
Line
Count
Source
69
130
   {
70
#if defined(BOTAN_HAS_VALGRIND)
71
   VALGRIND_MAKE_MEM_DEFINED(&p, sizeof(T));
72
#else
73
130
   BOTAN_UNUSED(p);
74
130
#endif
75
130
   }
void Botan::CT::unpoison<Botan::CT::Mask<unsigned short> const>(Botan::CT::Mask<unsigned short> const&)
Line
Count
Source
69
65
   {
70
#if defined(BOTAN_HAS_VALGRIND)
71
   VALGRIND_MAKE_MEM_DEFINED(&p, sizeof(T));
72
#else
73
65
   BOTAN_UNUSED(p);
74
65
#endif
75
65
   }
Unexecuted instantiation: void Botan::CT::unpoison<Botan::CT::Mask<unsigned char> >(Botan::CT::Mask<unsigned char>&)
76
77
/**
78
* A Mask type used for constant-time operations. A Mask<T> always has value
79
* either 0 (all bits cleared) or ~0 (all bits set). All operations in a Mask<T>
80
* are intended to compile to code which does not contain conditional jumps.
81
* This must be verified with tooling (eg binary disassembly or using valgrind)
82
* since you never know what a compiler might do.
83
*/
84
template<typename T>
85
class Mask
86
   {
87
   public:
88
      static_assert(std::is_unsigned<T>::value, "CT::Mask only defined for unsigned integer types");
89
90
      Mask(const Mask<T>& other) = default;
91
      Mask<T>& operator=(const Mask<T>& other) = default;
92
93
      /**
94
      * Derive a Mask from a Mask of a larger type
95
      */
96
      template<typename U>
97
      Mask(Mask<U> o) : m_mask(static_cast<T>(o.value()))
98
12.3k
         {
99
12.3k
         static_assert(sizeof(U) > sizeof(T), "sizes ok");
100
12.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
98
12.3k
         {
99
12.3k
         static_assert(sizeof(U) > sizeof(T), "sizes ok");
100
12.3k
         }
101
102
      /**
103
      * Return a Mask<T> with all bits set
104
      */
105
      static Mask<T> set()
106
172k
         {
107
172k
         return Mask<T>(static_cast<T>(~0));
108
172k
         }
Botan::CT::Mask<unsigned long>::set()
Line
Count
Source
106
59.9k
         {
107
59.9k
         return Mask<T>(static_cast<T>(~0));
108
59.9k
         }
Botan::CT::Mask<unsigned char>::set()
Line
Count
Source
106
112k
         {
107
112k
         return Mask<T>(static_cast<T>(~0));
108
112k
         }
109
110
      /**
111
      * Return a Mask<T> with all bits cleared
112
      */
113
      static Mask<T> cleared()
114
3.59M
         {
115
3.59M
         return Mask<T>(0);
116
3.59M
         }
Botan::CT::Mask<unsigned long>::cleared()
Line
Count
Source
114
3.59M
         {
115
3.59M
         return Mask<T>(0);
116
3.59M
         }
Botan::CT::Mask<unsigned char>::cleared()
Line
Count
Source
114
949
         {
115
949
         return Mask<T>(0);
116
949
         }
117
118
      /**
119
      * Return a Mask<T> which is set if v is != 0
120
      */
121
      static Mask<T> expand(T v)
122
1.29G
         {
123
1.29G
         return ~Mask<T>::is_zero(v);
124
1.29G
         }
Botan::CT::Mask<unsigned long>::expand(unsigned long)
Line
Count
Source
122
1.27G
         {
123
1.27G
         return ~Mask<T>::is_zero(v);
124
1.27G
         }
Botan::CT::Mask<unsigned char>::expand(unsigned char)
Line
Count
Source
122
16.6M
         {
123
16.6M
         return ~Mask<T>::is_zero(v);
124
16.6M
         }
Botan::CT::Mask<unsigned short>::expand(unsigned short)
Line
Count
Source
122
130
         {
123
130
         return ~Mask<T>::is_zero(v);
124
130
         }
125
126
      /**
127
      * Return a Mask<T> which is set if m is set
128
      */
129
      template<typename U>
130
      static Mask<T> expand(Mask<U> m)
131
566
         {
132
566
         static_assert(sizeof(U) < sizeof(T), "sizes ok");
133
566
         return ~Mask<T>::is_zero(m.value());
134
566
         }
135
136
      /**
137
      * Return a Mask<T> which is set if v is == 0 or cleared otherwise
138
      */
139
      static Mask<T> is_zero(T x)
140
4.12G
         {
141
4.12G
         return Mask<T>(ct_is_zero<T>(x));
142
4.12G
         }
Botan::CT::Mask<unsigned long>::is_zero(unsigned long)
Line
Count
Source
140
4.09G
         {
141
4.09G
         return Mask<T>(ct_is_zero<T>(x));
142
4.09G
         }
Botan::CT::Mask<unsigned char>::is_zero(unsigned char)
Line
Count
Source
140
37.1M
         {
141
37.1M
         return Mask<T>(ct_is_zero<T>(x));
142
37.1M
         }
Unexecuted instantiation: Botan::CT::Mask<unsigned int>::is_zero(unsigned int)
Botan::CT::Mask<unsigned short>::is_zero(unsigned short)
Line
Count
Source
140
34.0k
         {
141
34.0k
         return Mask<T>(ct_is_zero<T>(x));
142
34.0k
         }
143
144
      /**
145
      * Return a Mask<T> which is set if x == y
146
      */
147
      static Mask<T> is_equal(T x, T y)
148
2.79G
         {
149
2.79G
         return Mask<T>::is_zero(static_cast<T>(x ^ y));
150
2.79G
         }
Botan::CT::Mask<unsigned long>::is_equal(unsigned long, unsigned long)
Line
Count
Source
148
2.77G
         {
149
2.77G
         return Mask<T>::is_zero(static_cast<T>(x ^ y));
150
2.77G
         }
Botan::CT::Mask<unsigned char>::is_equal(unsigned char, unsigned char)
Line
Count
Source
148
19.9M
         {
149
19.9M
         return Mask<T>::is_zero(static_cast<T>(x ^ y));
150
19.9M
         }
Botan::CT::Mask<unsigned short>::is_equal(unsigned short, unsigned short)
Line
Count
Source
148
33.9k
         {
149
33.9k
         return Mask<T>::is_zero(static_cast<T>(x ^ y));
150
33.9k
         }
151
152
      /**
153
      * Return a Mask<T> which is set if x < y
154
      */
155
      static Mask<T> is_lt(T x, T y)
156
1.29G
         {
157
1.29G
         return Mask<T>(expand_top_bit<T>(x^((x^y) | ((x-y)^x))));
158
1.29G
         }
Botan::CT::Mask<unsigned long>::is_lt(unsigned long, unsigned long)
Line
Count
Source
156
1.29G
         {
157
1.29G
         return Mask<T>(expand_top_bit<T>(x^((x^y) | ((x-y)^x))));
158
1.29G
         }
Botan::CT::Mask<unsigned int>::is_lt(unsigned int, unsigned int)
Line
Count
Source
156
712k
         {
157
712k
         return Mask<T>(expand_top_bit<T>(x^((x^y) | ((x-y)^x))));
158
712k
         }
Botan::CT::Mask<unsigned char>::is_lt(unsigned char, unsigned char)
Line
Count
Source
156
1.14M
         {
157
1.14M
         return Mask<T>(expand_top_bit<T>(x^((x^y) | ((x-y)^x))));
158
1.14M
         }
Botan::CT::Mask<unsigned short>::is_lt(unsigned short, unsigned short)
Line
Count
Source
156
34.2k
         {
157
34.2k
         return Mask<T>(expand_top_bit<T>(x^((x^y) | ((x-y)^x))));
158
34.2k
         }
159
160
      /**
161
      * Return a Mask<T> which is set if x > y
162
      */
163
      static Mask<T> is_gt(T x, T y)
164
1.84M
         {
165
1.84M
         return Mask<T>::is_lt(y, x);
166
1.84M
         }
Botan::CT::Mask<unsigned long>::is_gt(unsigned long, unsigned long)
Line
Count
Source
164
1.81M
         {
165
1.81M
         return Mask<T>::is_lt(y, x);
166
1.81M
         }
Botan::CT::Mask<unsigned char>::is_gt(unsigned char, unsigned char)
Line
Count
Source
164
160
         {
165
160
         return Mask<T>::is_lt(y, x);
166
160
         }
Botan::CT::Mask<unsigned short>::is_gt(unsigned short, unsigned short)
Line
Count
Source
164
33.9k
         {
165
33.9k
         return Mask<T>::is_lt(y, x);
166
33.9k
         }
167
168
      /**
169
      * Return a Mask<T> which is set if x <= y
170
      */
171
      static Mask<T> is_lte(T x, T y)
172
1.83M
         {
173
1.83M
         return ~Mask<T>::is_gt(x, y);
174
1.83M
         }
Botan::CT::Mask<unsigned long>::is_lte(unsigned long, unsigned long)
Line
Count
Source
172
1.80M
         {
173
1.80M
         return ~Mask<T>::is_gt(x, y);
174
1.80M
         }
Botan::CT::Mask<unsigned short>::is_lte(unsigned short, unsigned short)
Line
Count
Source
172
33.9k
         {
173
33.9k
         return ~Mask<T>::is_gt(x, y);
174
33.9k
         }
175
176
      /**
177
      * Return a Mask<T> which is set if x >= y
178
      */
179
      static Mask<T> is_gte(T x, T y)
180
731k
         {
181
731k
         return ~Mask<T>::is_lt(x, y);
182
731k
         }
Botan::CT::Mask<unsigned int>::is_gte(unsigned int, unsigned int)
Line
Count
Source
180
712k
         {
181
712k
         return ~Mask<T>::is_lt(x, y);
182
712k
         }
Botan::CT::Mask<unsigned long>::is_gte(unsigned long, unsigned long)
Line
Count
Source
180
19.3k
         {
181
19.3k
         return ~Mask<T>::is_lt(x, y);
182
19.3k
         }
183
184
      static Mask<T> is_within_range(T v, T l, T u)
185
25.5M
         {
186
         //return Mask<T>::is_gte(v, l) & Mask<T>::is_lte(v, u);
187
188
25.5M
         const T v_lt_l = v^((v^l) | ((v-l)^v));
189
25.5M
         const T v_gt_u = u^((u^v) | ((u-v)^u));
190
25.5M
         const T either = v_lt_l | v_gt_u;
191
25.5M
         return ~Mask<T>(expand_top_bit(either));
192
25.5M
         }
193
194
      static Mask<T> is_any_of(T v, std::initializer_list<T> accepted)
195
8.52M
         {
196
8.52M
         T accept = 0;
197
198
8.52M
         for(auto a: accepted)
199
34.1M
            {
200
34.1M
            const T diff = a ^ v;
201
34.1M
            const T eq_zero = ~diff & (diff - 1);
202
34.1M
            accept |= eq_zero;
203
34.1M
            }
204
205
8.52M
         return Mask<T>(expand_top_bit(accept));
206
8.52M
         }
207
208
      /**
209
      * AND-combine two masks
210
      */
211
      Mask<T>& operator&=(Mask<T> o)
212
1.60M
         {
213
1.60M
         m_mask &= o.value();
214
1.60M
         return (*this);
215
1.60M
         }
Botan::CT::Mask<unsigned long>::operator&=(Botan::CT::Mask<unsigned long>)
Line
Count
Source
212
1.42M
         {
213
1.42M
         m_mask &= o.value();
214
1.42M
         return (*this);
215
1.42M
         }
Botan::CT::Mask<unsigned char>::operator&=(Botan::CT::Mask<unsigned char>)
Line
Count
Source
212
180k
         {
213
180k
         m_mask &= o.value();
214
180k
         return (*this);
215
180k
         }
216
217
      /**
218
      * XOR-combine two masks
219
      */
220
      Mask<T>& operator^=(Mask<T> o)
221
         {
222
         m_mask ^= o.value();
223
         return (*this);
224
         }
225
226
      /**
227
      * OR-combine two masks
228
      */
229
      Mask<T>& operator|=(Mask<T> o)
230
61.2M
         {
231
61.2M
         m_mask |= o.value();
232
61.2M
         return (*this);
233
61.2M
         }
Botan::CT::Mask<unsigned long>::operator|=(Botan::CT::Mask<unsigned long>)
Line
Count
Source
230
60.4M
         {
231
60.4M
         m_mask |= o.value();
232
60.4M
         return (*this);
233
60.4M
         }
Botan::CT::Mask<unsigned char>::operator|=(Botan::CT::Mask<unsigned char>)
Line
Count
Source
230
783k
         {
231
783k
         m_mask |= o.value();
232
783k
         return (*this);
233
783k
         }
Botan::CT::Mask<unsigned short>::operator|=(Botan::CT::Mask<unsigned short>)
Line
Count
Source
230
33.8k
         {
231
33.8k
         m_mask |= o.value();
232
33.8k
         return (*this);
233
33.8k
         }
234
235
      /**
236
      * AND-combine two masks
237
      */
238
      friend Mask<T> operator&(Mask<T> x, Mask<T> y)
239
123M
         {
240
123M
         return Mask<T>(x.value() & y.value());
241
123M
         }
Botan::CT::operator&(Botan::CT::Mask<unsigned long>, Botan::CT::Mask<unsigned long>)
Line
Count
Source
239
123M
         {
240
123M
         return Mask<T>(x.value() & y.value());
241
123M
         }
Botan::CT::operator&(Botan::CT::Mask<unsigned char>, Botan::CT::Mask<unsigned char>)
Line
Count
Source
239
562k
         {
240
562k
         return Mask<T>(x.value() & y.value());
241
562k
         }
Botan::CT::operator&(Botan::CT::Mask<unsigned short>, Botan::CT::Mask<unsigned short>)
Line
Count
Source
239
34.0k
         {
240
34.0k
         return Mask<T>(x.value() & y.value());
241
34.0k
         }
242
243
      /**
244
      * XOR-combine two masks
245
      */
246
      friend Mask<T> operator^(Mask<T> x, Mask<T> y)
247
276k
         {
248
276k
         return Mask<T>(x.value() ^ y.value());
249
276k
         }
250
251
      /**
252
      * OR-combine two masks
253
      */
254
      friend Mask<T> operator|(Mask<T> x, Mask<T> y)
255
123M
         {
256
123M
         return Mask<T>(x.value() | y.value());
257
123M
         }
Botan::CT::operator|(Botan::CT::Mask<unsigned long>, Botan::CT::Mask<unsigned long>)
Line
Count
Source
255
123M
         {
256
123M
         return Mask<T>(x.value() | y.value());
257
123M
         }
Botan::CT::operator|(Botan::CT::Mask<unsigned char>, Botan::CT::Mask<unsigned char>)
Line
Count
Source
255
180k
         {
256
180k
         return Mask<T>(x.value() | y.value());
257
180k
         }
258
259
      /**
260
      * Negate this mask
261
      */
262
      Mask<T> operator~() const
263
1.32G
         {
264
1.32G
         return Mask<T>(~value());
265
1.32G
         }
Botan::CT::Mask<unsigned long>::operator~() const
Line
Count
Source
263
1.27G
         {
264
1.27G
         return Mask<T>(~value());
265
1.27G
         }
Botan::CT::Mask<unsigned char>::operator~() const
Line
Count
Source
263
42.8M
         {
264
42.8M
         return Mask<T>(~value());
265
42.8M
         }
Botan::CT::Mask<unsigned int>::operator~() const
Line
Count
Source
263
712k
         {
264
712k
         return Mask<T>(~value());
265
712k
         }
Botan::CT::Mask<unsigned short>::operator~() const
Line
Count
Source
263
67.9k
         {
264
67.9k
         return Mask<T>(~value());
265
67.9k
         }
266
267
      /**
268
      * Return x if the mask is set, or otherwise zero
269
      */
270
      T if_set_return(T x) const
271
6.11G
         {
272
6.11G
         return m_mask & x;
273
6.11G
         }
Botan::CT::Mask<unsigned long>::if_set_return(unsigned long) const
Line
Count
Source
271
6.11G
         {
272
6.11G
         return m_mask & x;
273
6.11G
         }
Botan::CT::Mask<unsigned short>::if_set_return(unsigned short) const
Line
Count
Source
271
130
         {
272
130
         return m_mask & x;
273
130
         }
Botan::CT::Mask<unsigned char>::if_set_return(unsigned char) const
Line
Count
Source
271
180k
         {
272
180k
         return m_mask & x;
273
180k
         }
274
275
      /**
276
      * Return x if the mask is cleared, or otherwise zero
277
      */
278
      T if_not_set_return(T x) const
279
61.5M
         {
280
61.5M
         return ~m_mask & x;
281
61.5M
         }
Botan::CT::Mask<unsigned long>::if_not_set_return(unsigned long) const
Line
Count
Source
279
60.6M
         {
280
60.6M
         return ~m_mask & x;
281
60.6M
         }
Botan::CT::Mask<unsigned char>::if_not_set_return(unsigned char) const
Line
Count
Source
279
836k
         {
280
836k
         return ~m_mask & x;
281
836k
         }
Botan::CT::Mask<unsigned short>::if_not_set_return(unsigned short) const
Line
Count
Source
279
297
         {
280
297
         return ~m_mask & x;
281
297
         }
282
283
      /**
284
      * If this mask is set, return x, otherwise return y
285
      */
286
      T select(T x, T y) const
287
10.8G
         {
288
10.8G
         return choose(value(), x, y);
289
10.8G
         }
Botan::CT::Mask<unsigned long>::select(unsigned long, unsigned long) const
Line
Count
Source
287
10.7G
         {
288
10.7G
         return choose(value(), x, y);
289
10.7G
         }
Botan::CT::Mask<unsigned char>::select(unsigned char, unsigned char) const
Line
Count
Source
287
71.0M
         {
288
71.0M
         return choose(value(), x, y);
289
71.0M
         }
Botan::CT::Mask<unsigned int>::select(unsigned int, unsigned int) const
Line
Count
Source
287
712k
         {
288
712k
         return choose(value(), x, y);
289
712k
         }
Unexecuted instantiation: Botan::CT::Mask<unsigned short>::select(unsigned short, unsigned short) const
290
291
      T select_and_unpoison(T x, T y) const
292
696
         {
293
696
         T r = this->select(x, y);
294
696
         CT::unpoison(r);
295
696
         return r;
296
696
         }
Botan::CT::Mask<unsigned long>::select_and_unpoison(unsigned long, unsigned long) const
Line
Count
Source
292
536
         {
293
536
         T r = this->select(x, y);
294
536
         CT::unpoison(r);
295
536
         return r;
296
536
         }
Botan::CT::Mask<unsigned char>::select_and_unpoison(unsigned char, unsigned char) const
Line
Count
Source
292
160
         {
293
160
         T r = this->select(x, y);
294
160
         CT::unpoison(r);
295
160
         return r;
296
160
         }
297
298
      /**
299
      * If this mask is set, return x, otherwise return y
300
      */
301
      Mask<T> select_mask(Mask<T> x, Mask<T> y) const
302
948M
         {
303
948M
         return Mask<T>(select(x.value(), y.value()));
304
948M
         }
305
306
      /**
307
      * Conditionally set output to x or y, depending on if mask is set or
308
      * cleared (resp)
309
      */
310
      void select_n(T output[], const T x[], const T y[], size_t len) const
311
368M
         {
312
3.29G
         for(size_t i = 0; i != len; ++i)
313
2.92G
            output[i] = this->select(x[i], y[i]);
314
368M
         }
Botan::CT::Mask<unsigned long>::select_n(unsigned long*, unsigned long const*, unsigned long const*, unsigned long) const
Line
Count
Source
311
368M
         {
312
3.29G
         for(size_t i = 0; i != len; ++i)
313
2.92G
            output[i] = this->select(x[i], y[i]);
314
368M
         }
Unexecuted instantiation: Botan::CT::Mask<unsigned char>::select_n(unsigned char*, unsigned char const*, unsigned char const*, unsigned long) const
315
316
      /**
317
      * If this mask is set, zero out buf, otherwise do nothing
318
      */
319
      void if_set_zero_out(T buf[], size_t elems)
320
58.9k
         {
321
401k
         for(size_t i = 0; i != elems; ++i)
322
342k
            {
323
342k
            buf[i] = this->if_not_set_return(buf[i]);
324
342k
            }
325
58.9k
         }
326
327
      /**
328
      * Return the value of the mask, unpoisoned
329
      */
330
      T unpoisoned_value() const
331
12.3M
         {
332
12.3M
         T r = value();
333
12.3M
         CT::unpoison(r);
334
12.3M
         return r;
335
12.3M
         }
Botan::CT::Mask<unsigned long>::unpoisoned_value() const
Line
Count
Source
331
11.4M
         {
332
11.4M
         T r = value();
333
11.4M
         CT::unpoison(r);
334
11.4M
         return r;
335
11.4M
         }
Botan::CT::Mask<unsigned int>::unpoisoned_value() const
Line
Count
Source
331
712k
         {
332
712k
         T r = value();
333
712k
         CT::unpoison(r);
334
712k
         return r;
335
712k
         }
Botan::CT::Mask<unsigned char>::unpoisoned_value() const
Line
Count
Source
331
112k
         {
332
112k
         T r = value();
333
112k
         CT::unpoison(r);
334
112k
         return r;
335
112k
         }
Botan::CT::Mask<unsigned short>::unpoisoned_value() const
Line
Count
Source
331
65
         {
332
65
         T r = value();
333
65
         CT::unpoison(r);
334
65
         return r;
335
65
         }
336
337
      /**
338
      * Return true iff this mask is set
339
      */
340
      bool is_set() const
341
12.3M
         {
342
12.3M
         return unpoisoned_value() != 0;
343
12.3M
         }
Botan::CT::Mask<unsigned long>::is_set() const
Line
Count
Source
341
11.4M
         {
342
11.4M
         return unpoisoned_value() != 0;
343
11.4M
         }
Botan::CT::Mask<unsigned int>::is_set() const
Line
Count
Source
341
712k
         {
342
712k
         return unpoisoned_value() != 0;
343
712k
         }
Botan::CT::Mask<unsigned char>::is_set() const
Line
Count
Source
341
112k
         {
342
112k
         return unpoisoned_value() != 0;
343
112k
         }
Botan::CT::Mask<unsigned short>::is_set() const
Line
Count
Source
341
65
         {
342
65
         return unpoisoned_value() != 0;
343
65
         }
344
345
      /**
346
      * Return the underlying value of the mask
347
      */
348
      T value() const
349
14.7G
         {
350
14.7G
         return m_mask;
351
14.7G
         }
Botan::CT::Mask<unsigned long>::value() const
Line
Count
Source
349
14.6G
         {
350
14.6G
         return m_mask;
351
14.6G
         }
Botan::CT::Mask<unsigned char>::value() const
Line
Count
Source
349
116M
         {
350
116M
         return m_mask;
351
116M
         }
Botan::CT::Mask<unsigned int>::value() const
Line
Count
Source
349
2.13M
         {
350
2.13M
         return m_mask;
351
2.13M
         }
Botan::CT::Mask<unsigned short>::value() const
Line
Count
Source
349
169k
         {
350
169k
         return m_mask;
351
169k
         }
352
353
   private:
354
7.98G
      Mask(T m) : m_mask(m) {}
Botan::CT::Mask<unsigned long>::Mask(unsigned long)
Line
Count
Source
354
7.86G
      Mask(T m) : m_mask(m) {}
Botan::CT::Mask<unsigned char>::Mask(unsigned char)
Line
Count
Source
354
116M
      Mask(T m) : m_mask(m) {}
Botan::CT::Mask<unsigned int>::Mask(unsigned int)
Line
Count
Source
354
1.42M
      Mask(T m) : m_mask(m) {}
Botan::CT::Mask<unsigned short>::Mask(unsigned short)
Line
Count
Source
354
170k
      Mask(T m) : m_mask(m) {}
355
356
      T m_mask;
357
   };
358
359
template<typename T>
360
inline Mask<T> conditional_copy_mem(T cnd,
361
                                    T* to,
362
                                    const T* from0,
363
                                    const T* from1,
364
                                    size_t elems)
365
104M
   {
366
104M
   const auto mask = CT::Mask<T>::expand(cnd);
367
104M
   mask.select_n(to, from0, from1, elems);
368
104M
   return mask;
369
104M
   }
370
371
template<typename T>
372
inline void conditional_swap(bool cnd, T& x, T& y)
373
26.1M
   {
374
26.1M
   const auto swap = CT::Mask<T>::expand(cnd);
375
376
26.1M
   T t0 = swap.select(y, x);
377
26.1M
   T t1 = swap.select(x, y);
378
26.1M
   x = t0;
379
26.1M
   y = t1;
380
26.1M
   }
381
382
template<typename T>
383
inline void conditional_swap_ptr(bool cnd, T& x, T& y)
384
13.0M
   {
385
13.0M
   uintptr_t xp = reinterpret_cast<uintptr_t>(x);
386
13.0M
   uintptr_t yp = reinterpret_cast<uintptr_t>(y);
387
388
13.0M
   conditional_swap<uintptr_t>(cnd, xp, yp);
389
390
13.0M
   x = reinterpret_cast<T>(xp);
391
13.0M
   y = reinterpret_cast<T>(yp);
392
13.0M
   }
393
394
/**
395
* If bad_mask is unset, return input[offset:input_length] copied to new
396
* buffer. If bad_mask is set, return an empty vector. In all cases, the capacity
397
* of the vector is equal to input_length
398
*
399
* This function attempts to avoid leaking the following:
400
*  - if bad_input was set or not
401
*  - the value of offset
402
*  - the values in input[]
403
*
404
* This function leaks the value of input_length
405
*/
406
BOTAN_TEST_API
407
secure_vector<uint8_t> copy_output(CT::Mask<uint8_t> bad_input,
408
                                   const uint8_t input[],
409
                                   size_t input_length,
410
                                   size_t offset);
411
412
secure_vector<uint8_t> strip_leading_zeros(const uint8_t in[], size_t length);
413
414
inline secure_vector<uint8_t> strip_leading_zeros(const secure_vector<uint8_t>& in)
415
0
   {
416
0
   return strip_leading_zeros(in.data(), in.size());
417
0
   }
418
419
}
420
421
}
422
423
#endif