/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 | 93.9k | { |
50 | | #if defined(BOTAN_HAS_VALGRIND) |
51 | | VALGRIND_MAKE_MEM_UNDEFINED(p, n * sizeof(T)); |
52 | | #else |
53 | 93.9k | BOTAN_UNUSED(p, n); |
54 | 93.9k | #endif |
55 | 93.9k | } void Botan::CT::poison<unsigned long>(unsigned long const*, unsigned long) Line | Count | Source | 49 | 91.5k | { | 50 | | #if defined(BOTAN_HAS_VALGRIND) | 51 | | VALGRIND_MAKE_MEM_UNDEFINED(p, n * sizeof(T)); | 52 | | #else | 53 | 91.5k | BOTAN_UNUSED(p, n); | 54 | 91.5k | #endif | 55 | 91.5k | } |
void Botan::CT::poison<unsigned char>(unsigned char const*, unsigned long) Line | Count | Source | 49 | 2.42k | { | 50 | | #if defined(BOTAN_HAS_VALGRIND) | 51 | | VALGRIND_MAKE_MEM_UNDEFINED(p, n * sizeof(T)); | 52 | | #else | 53 | 2.42k | BOTAN_UNUSED(p, n); | 54 | 2.42k | #endif | 55 | 2.42k | } |
Unexecuted instantiation: void Botan::CT::poison<unsigned short>(unsigned short const*, unsigned long) 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 | 94.3k | { |
60 | | #if defined(BOTAN_HAS_VALGRIND) |
61 | | VALGRIND_MAKE_MEM_DEFINED(p, n * sizeof(T)); |
62 | | #else |
63 | 94.3k | BOTAN_UNUSED(p, n); |
64 | 94.3k | #endif |
65 | 94.3k | } void Botan::CT::unpoison<unsigned long>(unsigned long const*, unsigned long) Line | Count | Source | 59 | 90.9k | { | 60 | | #if defined(BOTAN_HAS_VALGRIND) | 61 | | VALGRIND_MAKE_MEM_DEFINED(p, n * sizeof(T)); | 62 | | #else | 63 | 90.9k | BOTAN_UNUSED(p, n); | 64 | 90.9k | #endif | 65 | 90.9k | } |
void Botan::CT::unpoison<unsigned char>(unsigned char const*, unsigned long) Line | Count | Source | 59 | 3.31k | { | 60 | | #if defined(BOTAN_HAS_VALGRIND) | 61 | | VALGRIND_MAKE_MEM_DEFINED(p, n * sizeof(T)); | 62 | | #else | 63 | 3.31k | BOTAN_UNUSED(p, n); | 64 | 3.31k | #endif | 65 | 3.31k | } |
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) |
66 | | |
67 | | template<typename T> |
68 | | inline void unpoison(T& p) |
69 | 1.11G | { |
70 | | #if defined(BOTAN_HAS_VALGRIND) |
71 | | VALGRIND_MAKE_MEM_DEFINED(&p, sizeof(T)); |
72 | | #else |
73 | 1.11G | BOTAN_UNUSED(p); |
74 | 1.11G | #endif |
75 | 1.11G | } void Botan::CT::unpoison<unsigned long>(unsigned long&) Line | Count | Source | 69 | 955M | { | 70 | | #if defined(BOTAN_HAS_VALGRIND) | 71 | | VALGRIND_MAKE_MEM_DEFINED(&p, sizeof(T)); | 72 | | #else | 73 | 955M | BOTAN_UNUSED(p); | 74 | 955M | #endif | 75 | 955M | } |
void Botan::CT::unpoison<unsigned long const>(unsigned long const&) Line | Count | Source | 69 | 12.9M | { | 70 | | #if defined(BOTAN_HAS_VALGRIND) | 71 | | VALGRIND_MAKE_MEM_DEFINED(&p, sizeof(T)); | 72 | | #else | 73 | 12.9M | BOTAN_UNUSED(p); | 74 | 12.9M | #endif | 75 | 12.9M | } |
void Botan::CT::unpoison<long>(long&) Line | Count | Source | 69 | 144M | { | 70 | | #if defined(BOTAN_HAS_VALGRIND) | 71 | | VALGRIND_MAKE_MEM_DEFINED(&p, sizeof(T)); | 72 | | #else | 73 | 144M | BOTAN_UNUSED(p); | 74 | 144M | #endif | 75 | 144M | } |
void Botan::CT::unpoison<unsigned char>(unsigned char&) Line | Count | Source | 69 | 101k | { | 70 | | #if defined(BOTAN_HAS_VALGRIND) | 71 | | VALGRIND_MAKE_MEM_DEFINED(&p, sizeof(T)); | 72 | | #else | 73 | 101k | BOTAN_UNUSED(p); | 74 | 101k | #endif | 75 | 101k | } |
void Botan::CT::unpoison<unsigned char const>(unsigned char const&) Line | Count | Source | 69 | 213 | { | 70 | | #if defined(BOTAN_HAS_VALGRIND) | 71 | | VALGRIND_MAKE_MEM_DEFINED(&p, sizeof(T)); | 72 | | #else | 73 | 213 | BOTAN_UNUSED(p); | 74 | 213 | #endif | 75 | 213 | } |
void Botan::CT::unpoison<unsigned short>(unsigned short&) Line | Count | Source | 69 | 182 | { | 70 | | #if defined(BOTAN_HAS_VALGRIND) | 71 | | VALGRIND_MAKE_MEM_DEFINED(&p, sizeof(T)); | 72 | | #else | 73 | 182 | BOTAN_UNUSED(p); | 74 | 182 | #endif | 75 | 182 | } |
void Botan::CT::unpoison<Botan::CT::Mask<unsigned short> const>(Botan::CT::Mask<unsigned short> const&) Line | Count | Source | 69 | 91 | { | 70 | | #if defined(BOTAN_HAS_VALGRIND) | 71 | | VALGRIND_MAKE_MEM_DEFINED(&p, sizeof(T)); | 72 | | #else | 73 | 91 | BOTAN_UNUSED(p); | 74 | 91 | #endif | 75 | 91 | } |
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 | 3.14k | { |
99 | 3.14k | static_assert(sizeof(U) > sizeof(T), "sizes ok"); |
100 | 3.14k | } 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 | 3.14k | { | 99 | 3.14k | static_assert(sizeof(U) > sizeof(T), "sizes ok"); | 100 | 3.14k | } |
|
101 | | |
102 | | /** |
103 | | * Return a Mask<T> with all bits set |
104 | | */ |
105 | | static Mask<T> set() |
106 | 193k | { |
107 | 193k | return Mask<T>(static_cast<T>(~0)); |
108 | 193k | } Botan::CT::Mask<unsigned long>::set() Line | Count | Source | 106 | 91.9k | { | 107 | 91.9k | return Mask<T>(static_cast<T>(~0)); | 108 | 91.9k | } |
Botan::CT::Mask<unsigned char>::set() Line | Count | Source | 106 | 101k | { | 107 | 101k | return Mask<T>(static_cast<T>(~0)); | 108 | 101k | } |
|
109 | | |
110 | | /** |
111 | | * Return a Mask<T> with all bits cleared |
112 | | */ |
113 | | static Mask<T> cleared() |
114 | 4.61M | { |
115 | 4.61M | return Mask<T>(0); |
116 | 4.61M | } Botan::CT::Mask<unsigned long>::cleared() Line | Count | Source | 114 | 4.61M | { | 115 | 4.61M | return Mask<T>(0); | 116 | 4.61M | } |
Botan::CT::Mask<unsigned char>::cleared() Line | Count | Source | 114 | 442 | { | 115 | 442 | return Mask<T>(0); | 116 | 442 | } |
|
117 | | |
118 | | /** |
119 | | * Return a Mask<T> which is set if v is != 0 |
120 | | */ |
121 | | static Mask<T> expand(T v) |
122 | 2.45G | { |
123 | 2.45G | return ~Mask<T>::is_zero(v); |
124 | 2.45G | } Botan::CT::Mask<unsigned long>::expand(unsigned long) Line | Count | Source | 122 | 2.43G | { | 123 | 2.43G | return ~Mask<T>::is_zero(v); | 124 | 2.43G | } |
Botan::CT::Mask<unsigned char>::expand(unsigned char) Line | Count | Source | 122 | 23.5M | { | 123 | 23.5M | return ~Mask<T>::is_zero(v); | 124 | 23.5M | } |
Botan::CT::Mask<unsigned short>::expand(unsigned short) Line | Count | Source | 122 | 182 | { | 123 | 182 | return ~Mask<T>::is_zero(v); | 124 | 182 | } |
|
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 | 297 | { |
132 | 297 | static_assert(sizeof(U) < sizeof(T), "sizes ok"); |
133 | 297 | return ~Mask<T>::is_zero(m.value()); |
134 | 297 | } |
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 | 5.80G | { |
141 | 5.80G | return Mask<T>(ct_is_zero<T>(x)); |
142 | 5.80G | } Botan::CT::Mask<unsigned long>::is_zero(unsigned long) Line | Count | Source | 140 | 5.76G | { | 141 | 5.76G | return Mask<T>(ct_is_zero<T>(x)); | 142 | 5.76G | } |
Botan::CT::Mask<unsigned char>::is_zero(unsigned char) Line | Count | Source | 140 | 41.9M | { | 141 | 41.9M | return Mask<T>(ct_is_zero<T>(x)); | 142 | 41.9M | } |
Unexecuted instantiation: Botan::CT::Mask<unsigned int>::is_zero(unsigned int) Botan::CT::Mask<unsigned short>::is_zero(unsigned short) Line | Count | Source | 140 | 19.0k | { | 141 | 19.0k | return Mask<T>(ct_is_zero<T>(x)); | 142 | 19.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 | 3.29G | { |
149 | 3.29G | return Mask<T>::is_zero(static_cast<T>(x ^ y)); |
150 | 3.29G | } Botan::CT::Mask<unsigned long>::is_equal(unsigned long, unsigned long) Line | Count | Source | 148 | 3.27G | { | 149 | 3.27G | return Mask<T>::is_zero(static_cast<T>(x ^ y)); | 150 | 3.27G | } |
Botan::CT::Mask<unsigned char>::is_equal(unsigned char, unsigned char) Line | Count | Source | 148 | 18.0M | { | 149 | 18.0M | return Mask<T>::is_zero(static_cast<T>(x ^ y)); | 150 | 18.0M | } |
Botan::CT::Mask<unsigned short>::is_equal(unsigned short, unsigned short) Line | Count | Source | 148 | 18.8k | { | 149 | 18.8k | return Mask<T>::is_zero(static_cast<T>(x ^ y)); | 150 | 18.8k | } |
|
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 | 2.34G | { |
157 | 2.34G | return Mask<T>(expand_top_bit<T>(x^((x^y) | ((x-y)^x)))); |
158 | 2.34G | } Botan::CT::Mask<unsigned long>::is_lt(unsigned long, unsigned long) Line | Count | Source | 156 | 2.34G | { | 157 | 2.34G | return Mask<T>(expand_top_bit<T>(x^((x^y) | ((x-y)^x)))); | 158 | 2.34G | } |
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 | 18.9k | { | 157 | 18.9k | return Mask<T>(expand_top_bit<T>(x^((x^y) | ((x-y)^x)))); | 158 | 18.9k | } |
|
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.82M | { |
165 | 1.82M | return Mask<T>::is_lt(y, x); |
166 | 1.82M | } Botan::CT::Mask<unsigned long>::is_gt(unsigned long, unsigned long) Line | Count | Source | 164 | 1.80M | { | 165 | 1.80M | return Mask<T>::is_lt(y, x); | 166 | 1.80M | } |
Unexecuted instantiation: Botan::CT::Mask<unsigned char>::is_gt(unsigned char, unsigned char) Botan::CT::Mask<unsigned short>::is_gt(unsigned short, unsigned short) Line | Count | Source | 164 | 18.8k | { | 165 | 18.8k | return Mask<T>::is_lt(y, x); | 166 | 18.8k | } |
|
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.82M | { |
173 | 1.82M | return ~Mask<T>::is_gt(x, y); |
174 | 1.82M | } 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 | 18.8k | { | 173 | 18.8k | return ~Mask<T>::is_gt(x, y); | 174 | 18.8k | } |
|
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 | 744M | { |
181 | 744M | return ~Mask<T>::is_lt(x, y); |
182 | 744M | } |
183 | | |
184 | | static Mask<T> is_within_range(T v, T l, T u) |
185 | 24.4M | { |
186 | | //return Mask<T>::is_gte(v, l) & Mask<T>::is_lte(v, u); |
187 | | |
188 | 24.4M | const T v_lt_l = v^((v^l) | ((v-l)^v)); |
189 | 24.4M | const T v_gt_u = u^((u^v) | ((u-v)^u)); |
190 | 24.4M | const T either = v_lt_l | v_gt_u; |
191 | 24.4M | return ~Mask<T>(expand_top_bit(either)); |
192 | 24.4M | } |
193 | | |
194 | | static Mask<T> is_any_of(T v, std::initializer_list<T> accepted) |
195 | 8.13M | { |
196 | 8.13M | T accept = 0; |
197 | | |
198 | 8.13M | for(auto a: accepted) |
199 | 32.5M | { |
200 | 32.5M | const T diff = a ^ v; |
201 | 32.5M | const T eq_zero = ~diff & (diff - 1); |
202 | 32.5M | accept |= eq_zero; |
203 | 32.5M | } |
204 | | |
205 | 8.13M | return Mask<T>(expand_top_bit(accept)); |
206 | 8.13M | } |
207 | | |
208 | | /** |
209 | | * AND-combine two masks |
210 | | */ |
211 | | Mask<T>& operator&=(Mask<T> o) |
212 | 1.97M | { |
213 | 1.97M | m_mask &= o.value(); |
214 | 1.97M | return (*this); |
215 | 1.97M | } Botan::CT::Mask<unsigned long>::operator&=(Botan::CT::Mask<unsigned long>) Line | Count | Source | 212 | 1.77M | { | 213 | 1.77M | m_mask &= o.value(); | 214 | 1.77M | return (*this); | 215 | 1.77M | } |
Botan::CT::Mask<unsigned char>::operator&=(Botan::CT::Mask<unsigned char>) Line | Count | Source | 212 | 199k | { | 213 | 199k | m_mask &= o.value(); | 214 | 199k | return (*this); | 215 | 199k | } |
|
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 | 74.5M | { |
231 | 74.5M | m_mask |= o.value(); |
232 | 74.5M | return (*this); |
233 | 74.5M | } Botan::CT::Mask<unsigned long>::operator|=(Botan::CT::Mask<unsigned long>) Line | Count | Source | 230 | 74.0M | { | 231 | 74.0M | m_mask |= o.value(); | 232 | 74.0M | return (*this); | 233 | 74.0M | } |
Botan::CT::Mask<unsigned char>::operator|=(Botan::CT::Mask<unsigned char>) Line | Count | Source | 230 | 436k | { | 231 | 436k | m_mask |= o.value(); | 232 | 436k | return (*this); | 233 | 436k | } |
Botan::CT::Mask<unsigned short>::operator|=(Botan::CT::Mask<unsigned short>) Line | Count | Source | 230 | 18.7k | { | 231 | 18.7k | m_mask |= o.value(); | 232 | 18.7k | return (*this); | 233 | 18.7k | } |
|
234 | | |
235 | | /** |
236 | | * AND-combine two masks |
237 | | */ |
238 | | friend Mask<T> operator&(Mask<T> x, Mask<T> y) |
239 | 145M | { |
240 | 145M | return Mask<T>(x.value() & y.value()); |
241 | 145M | } Botan::CT::operator&(Botan::CT::Mask<unsigned long>, Botan::CT::Mask<unsigned long>) Line | Count | Source | 239 | 145M | { | 240 | 145M | return Mask<T>(x.value() & y.value()); | 241 | 145M | } |
Botan::CT::operator&(Botan::CT::Mask<unsigned char>, Botan::CT::Mask<unsigned char>) Line | Count | Source | 239 | 399k | { | 240 | 399k | return Mask<T>(x.value() & y.value()); | 241 | 399k | } |
Botan::CT::operator&(Botan::CT::Mask<unsigned short>, Botan::CT::Mask<unsigned short>) Line | Count | Source | 239 | 18.9k | { | 240 | 18.9k | return Mask<T>(x.value() & y.value()); | 241 | 18.9k | } |
|
242 | | |
243 | | /** |
244 | | * XOR-combine two masks |
245 | | */ |
246 | | friend Mask<T> operator^(Mask<T> x, Mask<T> y) |
247 | 263k | { |
248 | 263k | return Mask<T>(x.value() ^ y.value()); |
249 | 263k | } |
250 | | |
251 | | /** |
252 | | * OR-combine two masks |
253 | | */ |
254 | | friend Mask<T> operator|(Mask<T> x, Mask<T> y) |
255 | 889M | { |
256 | 889M | return Mask<T>(x.value() | y.value()); |
257 | 889M | } Botan::CT::operator|(Botan::CT::Mask<unsigned long>, Botan::CT::Mask<unsigned long>) Line | Count | Source | 255 | 889M | { | 256 | 889M | return Mask<T>(x.value() | y.value()); | 257 | 889M | } |
Botan::CT::operator|(Botan::CT::Mask<unsigned char>, Botan::CT::Mask<unsigned char>) Line | Count | Source | 255 | 199k | { | 256 | 199k | return Mask<T>(x.value() | y.value()); | 257 | 199k | } |
|
258 | | |
259 | | /** |
260 | | * Negate this mask |
261 | | */ |
262 | | Mask<T> operator~() const |
263 | 3.22G | { |
264 | 3.22G | return Mask<T>(~value()); |
265 | 3.22G | } Botan::CT::Mask<unsigned long>::operator~() const Line | Count | Source | 263 | 3.17G | { | 264 | 3.17G | return Mask<T>(~value()); | 265 | 3.17G | } |
Botan::CT::Mask<unsigned char>::operator~() const Line | Count | Source | 263 | 48.1M | { | 264 | 48.1M | return Mask<T>(~value()); | 265 | 48.1M | } |
Botan::CT::Mask<unsigned short>::operator~() const Line | Count | Source | 263 | 37.7k | { | 264 | 37.7k | return Mask<T>(~value()); | 265 | 37.7k | } |
|
266 | | |
267 | | /** |
268 | | * Return x if the mask is set, or otherwise zero |
269 | | */ |
270 | | T if_set_return(T x) const |
271 | 7.37G | { |
272 | 7.37G | return m_mask & x; |
273 | 7.37G | } Botan::CT::Mask<unsigned long>::if_set_return(unsigned long) const Line | Count | Source | 271 | 7.37G | { | 272 | 7.37G | return m_mask & x; | 273 | 7.37G | } |
Botan::CT::Mask<unsigned char>::if_set_return(unsigned char) const Line | Count | Source | 271 | 199k | { | 272 | 199k | return m_mask & x; | 273 | 199k | } |
Botan::CT::Mask<unsigned short>::if_set_return(unsigned short) const Line | Count | Source | 271 | 182 | { | 272 | 182 | return m_mask & x; | 273 | 182 | } |
|
274 | | |
275 | | /** |
276 | | * Return x if the mask is cleared, or otherwise zero |
277 | | */ |
278 | | T if_not_set_return(T x) const |
279 | 75.2M | { |
280 | 75.2M | return ~m_mask & x; |
281 | 75.2M | } Botan::CT::Mask<unsigned long>::if_not_set_return(unsigned long) const Line | Count | Source | 279 | 74.4M | { | 280 | 74.4M | return ~m_mask & x; | 281 | 74.4M | } |
Botan::CT::Mask<unsigned char>::if_not_set_return(unsigned char) const Line | Count | Source | 279 | 794k | { | 280 | 794k | return ~m_mask & x; | 281 | 794k | } |
Botan::CT::Mask<unsigned short>::if_not_set_return(unsigned short) const Line | Count | Source | 279 | 91 | { | 280 | 91 | return ~m_mask & x; | 281 | 91 | } |
|
282 | | |
283 | | /** |
284 | | * If this mask is set, return x, otherwise return y |
285 | | */ |
286 | | T select(T x, T y) const |
287 | 14.7G | { |
288 | 14.7G | return choose(value(), x, y); |
289 | 14.7G | } Botan::CT::Mask<unsigned long>::select(unsigned long, unsigned long) const Line | Count | Source | 287 | 14.6G | { | 288 | 14.6G | return choose(value(), x, y); | 289 | 14.6G | } |
Botan::CT::Mask<unsigned char>::select(unsigned char, unsigned char) const Line | Count | Source | 287 | 74.4M | { | 288 | 74.4M | return choose(value(), x, y); | 289 | 74.4M | } |
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 | 0 | { |
293 | 0 | T r = this->select(x, y); |
294 | 0 | CT::unpoison(r); |
295 | 0 | return r; |
296 | 0 | } Unexecuted instantiation: Botan::CT::Mask<unsigned long>::select_and_unpoison(unsigned long, unsigned long) const Unexecuted instantiation: Botan::CT::Mask<unsigned char>::select_and_unpoison(unsigned char, unsigned char) const |
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 | 1.19G | { |
303 | 1.19G | return Mask<T>(select(x.value(), y.value())); |
304 | 1.19G | } |
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 | 443M | { |
312 | 3.88G | for(size_t i = 0; i != len; ++i) |
313 | 3.43G | output[i] = this->select(x[i], y[i]); |
314 | 443M | } Botan::CT::Mask<unsigned long>::select_n(unsigned long*, unsigned long const*, unsigned long const*, unsigned long) const Line | Count | Source | 311 | 443M | { | 312 | 3.88G | for(size_t i = 0; i != len; ++i) | 313 | 3.43G | output[i] = this->select(x[i], y[i]); | 314 | 443M | } |
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 | 90.9k | { |
321 | 583k | for(size_t i = 0; i != elems; ++i) |
322 | 492k | { |
323 | 492k | buf[i] = this->if_not_set_return(buf[i]); |
324 | 492k | } |
325 | 90.9k | } |
326 | | |
327 | | /** |
328 | | * Return the value of the mask, unpoisoned |
329 | | */ |
330 | | T unpoisoned_value() const |
331 | 758M | { |
332 | 758M | T r = value(); |
333 | 758M | CT::unpoison(r); |
334 | 758M | return r; |
335 | 758M | } Botan::CT::Mask<unsigned long>::unpoisoned_value() const Line | Count | Source | 331 | 758M | { | 332 | 758M | T r = value(); | 333 | 758M | CT::unpoison(r); | 334 | 758M | return r; | 335 | 758M | } |
Botan::CT::Mask<unsigned char>::unpoisoned_value() const Line | Count | Source | 331 | 101k | { | 332 | 101k | T r = value(); | 333 | 101k | CT::unpoison(r); | 334 | 101k | return r; | 335 | 101k | } |
Botan::CT::Mask<unsigned short>::unpoisoned_value() const Line | Count | Source | 331 | 91 | { | 332 | 91 | T r = value(); | 333 | 91 | CT::unpoison(r); | 334 | 91 | return r; | 335 | 91 | } |
|
336 | | |
337 | | /** |
338 | | * Return true iff this mask is set |
339 | | */ |
340 | | bool is_set() const |
341 | 758M | { |
342 | 758M | return unpoisoned_value() != 0; |
343 | 758M | } Botan::CT::Mask<unsigned long>::is_set() const Line | Count | Source | 341 | 758M | { | 342 | 758M | return unpoisoned_value() != 0; | 343 | 758M | } |
Botan::CT::Mask<unsigned short>::is_set() const Line | Count | Source | 341 | 91 | { | 342 | 91 | return unpoisoned_value() != 0; | 343 | 91 | } |
Botan::CT::Mask<unsigned char>::is_set() const Line | Count | Source | 341 | 100k | { | 342 | 100k | return unpoisoned_value() != 0; | 343 | 100k | } |
|
344 | | |
345 | | /** |
346 | | * Return the underlying value of the mask |
347 | | */ |
348 | | T value() const |
349 | 23.4G | { |
350 | 23.4G | return m_mask; |
351 | 23.4G | } Botan::CT::Mask<unsigned long>::value() const Line | Count | Source | 349 | 23.3G | { | 350 | 23.3G | return m_mask; | 351 | 23.3G | } |
Botan::CT::Mask<unsigned char>::value() const Line | Count | Source | 349 | 124M | { | 350 | 124M | return m_mask; | 351 | 124M | } |
Unexecuted instantiation: Botan::CT::Mask<unsigned int>::value() const Botan::CT::Mask<unsigned short>::value() const Line | Count | Source | 349 | 94.4k | { | 350 | 94.4k | return m_mask; | 351 | 94.4k | } |
|
352 | | |
353 | | private: |
354 | 13.6G | Mask(T m) : m_mask(m) {} Botan::CT::Mask<unsigned long>::Mask(unsigned long) Line | Count | Source | 354 | 13.5G | Mask(T m) : m_mask(m) {} |
Botan::CT::Mask<unsigned char>::Mask(unsigned char) Line | Count | Source | 354 | 124M | Mask(T m) : m_mask(m) {} |
Unexecuted instantiation: Botan::CT::Mask<unsigned int>::Mask(unsigned int) Botan::CT::Mask<unsigned short>::Mask(unsigned short) Line | Count | Source | 354 | 94.5k | 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 | 140M | { |
366 | 140M | const auto mask = CT::Mask<T>::expand(cnd); |
367 | 140M | mask.select_n(to, from0, from1, elems); |
368 | 140M | return mask; |
369 | 140M | } |
370 | | |
371 | | template<typename T> |
372 | | inline void conditional_swap(bool cnd, T& x, T& y) |
373 | 36.7M | { |
374 | 36.7M | const auto swap = CT::Mask<T>::expand(cnd); |
375 | | |
376 | 36.7M | T t0 = swap.select(y, x); |
377 | 36.7M | T t1 = swap.select(x, y); |
378 | 36.7M | x = t0; |
379 | 36.7M | y = t1; |
380 | 36.7M | } |
381 | | |
382 | | template<typename T> |
383 | | inline void conditional_swap_ptr(bool cnd, T& x, T& y) |
384 | 18.3M | { |
385 | 18.3M | uintptr_t xp = reinterpret_cast<uintptr_t>(x); |
386 | 18.3M | uintptr_t yp = reinterpret_cast<uintptr_t>(y); |
387 | | |
388 | 18.3M | conditional_swap<uintptr_t>(cnd, xp, yp); |
389 | | |
390 | 18.3M | x = reinterpret_cast<T>(xp); |
391 | 18.3M | y = reinterpret_cast<T>(yp); |
392 | 18.3M | } |
393 | | |
394 | | /** |
395 | | * If bad_input is unset, return input[offset:input_length] copied to new |
396 | | * buffer. If bad_input 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 |