Botan 2.13.0 Crypto and TLS for C++11

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

mem_ops.h
Go to the documentation of this file.
1 /*
2 * Memory Operations
3 * (C) 1999-2009,2012,2015 Jack Lloyd
4 *
5 * Botan is released under the Simplified BSD License (see license.txt)
6 */
7
8 #ifndef BOTAN_MEMORY_OPS_H_
9 #define BOTAN_MEMORY_OPS_H_
10
11 #include <botan/types.h>
12 #include <cstring>
13 #include <type_traits>
14 #include <vector>
15
16 namespace Botan {
17
18 /**
19 * Allocate a memory buffer by some method. This should only be used for
20 * primitive types (uint8_t, uint32_t, etc).
21 *
22 * @param elems the number of elements
23 * @param elem_size the size of each element
24 * @return pointer to allocated and zeroed memory, or throw std::bad_alloc on failure
25 */
26 BOTAN_PUBLIC_API(2,3) BOTAN_MALLOC_FN void* allocate_memory(size_t elems, size_t elem_size);
27
28 /**
29 * Free a pointer returned by allocate_memory
30 * @param p the pointer returned by allocate_memory
31 * @param elems the number of elements, as passed to allocate_memory
32 * @param elem_size the size of each element, as passed to allocate_memory
33 */
34 BOTAN_PUBLIC_API(2,3) void deallocate_memory(void* p, size_t elems, size_t elem_size);
35
36 /**
37 * Ensure the allocator is initialized
38 */
39 void initialize_allocator();
40
41 class Allocator_Initializer
42 {
43 public:
44 Allocator_Initializer() { initialize_allocator(); }
45 };
46
47 /**
48 * Scrub memory contents in a way that a compiler should not elide,
49 * using some system specific technique. Note that this function might
50 * not zero the memory (for example, in some hypothetical
51 * implementation it might combine the memory contents with the output
52 * of a system PRNG), but if you can detect any difference in behavior
53 * at runtime then the clearing is side-effecting and you can just
54 * use `clear_mem`.
55 *
56 * Use this function to scrub memory just before deallocating it, or on
57 * a stack buffer before returning from the function.
58 *
59 * @param ptr a pointer to memory to scrub
60 * @param n the number of bytes pointed to by ptr
61 */
62 BOTAN_PUBLIC_API(2,0) void secure_scrub_memory(void* ptr, size_t n);
63
64 /**
65 * Memory comparison, input insensitive
66 * @param x a pointer to an array
67 * @param y a pointer to another array
68 * @param len the number of Ts in x and y
69 * @return 0xFF iff x[i] == y[i] forall i in [0...n) or 0x00 otherwise
70 */
71 BOTAN_PUBLIC_API(2,9) uint8_t ct_compare_u8(const uint8_t x[],
72 const uint8_t y[],
73 size_t len);
74
75 /**
76 * Memory comparison, input insensitive
77 * @param x a pointer to an array
78 * @param y a pointer to another array
79 * @param len the number of Ts in x and y
80 * @return true iff x[i] == y[i] forall i in [0...n)
81 */
82 inline bool constant_time_compare(const uint8_t x[],
83 const uint8_t y[],
84 size_t len)
85 {
86 return ct_compare_u8(x, y, len) == 0xFF;
87 }
88
89 /**
90 * Zero out some bytes
91 * @param ptr a pointer to memory to zero
92 * @param bytes the number of bytes to zero in ptr
93 */
94 inline void clear_bytes(void* ptr, size_t bytes)
95 {
96 if(bytes > 0)
97 {
98 std::memset(ptr, 0, bytes);
99 }
100 }
101
102 /**
103 * Zero memory before use. This simply calls memset and should not be
104 * used in cases where the compiler cannot see the call as a
105 * side-effecting operation (for example, if calling clear_mem before
106 * deallocating memory, the compiler would be allowed to omit the call
107 * to memset entirely under the as-if rule.)
108 *
109 * @param ptr a pointer to an array of Ts to zero
110 * @param n the number of Ts pointed to by ptr
111 */
112 template<typename T> inline void clear_mem(T* ptr, size_t n)
113 {
114 clear_bytes(ptr, sizeof(T)*n);
115 }
116
117
118
119 // is_trivially_copyable is missing in g++ < 5.0
120 #if !__clang__ && __GNUG__ && __GNUC__ < 5
121 #define BOTAN_IS_TRIVIALLY_COPYABLE(T) true
122 #else
123 #define BOTAN_IS_TRIVIALLY_COPYABLE(T) std::is_trivially_copyable<T>::value
124 #endif
125
126 /**
127 * Copy memory
128 * @param out the destination array
129 * @param in the source array
130 * @param n the number of elements of in/out
131 */
132 template<typename T> inline void copy_mem(T* out, const T* in, size_t n)
133 {
134 static_assert(std::is_trivial<typename std::decay<T>::type>::value, "");
135 BOTAN_ASSERT_IMPLICATION(n > 0, in != nullptr && out != nullptr,
136 "If n > 0 then args are not null");
137
138 if(in != nullptr && out != nullptr && n > 0)
139 {
140 std::memmove(out, in, sizeof(T)*n);
141 }
142 }
143
144 template<typename T> inline void typecast_copy(uint8_t out[], T in[], size_t N)
145 {
146 static_assert(BOTAN_IS_TRIVIALLY_COPYABLE(T), "");
147 std::memcpy(out, in, sizeof(T)*N);
148 }
149
150 template<typename T> inline void typecast_copy(T out[], const uint8_t in[], size_t N)
151 {
152 static_assert(std::is_trivial<T>::value, "");
153 std::memcpy(out, in, sizeof(T)*N);
154 }
155
156 template<typename T> inline void typecast_copy(uint8_t out[], T in)
157 {
158 typecast_copy(out, &in, 1);
159 }
160
161 template<typename T> inline void typecast_copy(T& out, const uint8_t in[])
162 {
163 static_assert(std::is_trivial<typename std::decay<T>::type>::value, "");
164 typecast_copy(&out, in, 1);
165 }
166
167 template <class To, class From> inline To typecast_copy(const From *src) noexcept
168 {
169 static_assert(BOTAN_IS_TRIVIALLY_COPYABLE(From) && std::is_trivial<To>::value, "");
170 To dst;
171 std::memcpy(&dst, src, sizeof(To));
172 return dst;
173 }
174
175 /**
176 * Set memory to a fixed value
177 * @param ptr a pointer to an array of bytes
178 * @param n the number of Ts pointed to by ptr
179 * @param val the value to set each byte to
180 */
181 inline void set_mem(uint8_t* ptr, size_t n, uint8_t val)
182 {
183 if(n > 0)
184 {
185 std::memset(ptr, val, n);
186 }
187 }
188
189 inline const uint8_t* cast_char_ptr_to_uint8(const char* s)
190 {
191 return reinterpret_cast<const uint8_t*>(s);
192 }
193
194 inline const char* cast_uint8_ptr_to_char(const uint8_t* b)
195 {
196 return reinterpret_cast<const char*>(b);
197 }
198
199 inline uint8_t* cast_char_ptr_to_uint8(char* s)
200 {
201 return reinterpret_cast<uint8_t*>(s);
202 }
203
204 inline char* cast_uint8_ptr_to_char(uint8_t* b)
205 {
206 return reinterpret_cast<char*>(b);
207 }
208
209 /**
210 * Memory comparison, input insensitive
211 * @param p1 a pointer to an array
212 * @param p2 a pointer to another array
213 * @param n the number of Ts in p1 and p2
214 * @return true iff p1[i] == p2[i] forall i in [0...n)
215 */
216 template<typename T> inline bool same_mem(const T* p1, const T* p2, size_t n)
217 {
218 volatile T difference = 0;
219
220 for(size_t i = 0; i != n; ++i)
221 difference |= (p1[i] ^ p2[i]);
222
223 return difference == 0;
224 }
225
226 /**
227 * XOR arrays. Postcondition out[i] = in[i] ^ out[i] forall i = 0...length
228 * @param out the input/output buffer
229 * @param in the read-only input buffer
230 * @param length the length of the buffers
231 */
232 inline void xor_buf(uint8_t out[],
233 const uint8_t in[],
234 size_t length)
235 {
236 const size_t blocks = length - (length % 32);
237
238 for(size_t i = 0; i != blocks; i += 32)
239 {
240 uint64_t x[4];
241 uint64_t y[4];
242
243 typecast_copy(x, out + i, 4);
244 typecast_copy(y, in + i, 4);
245
246 x[0] ^= y[0];
247 x[1] ^= y[1];
248 x[2] ^= y[2];
249 x[3] ^= y[3];
250
251 typecast_copy(out + i, x, 4);
252 }
253
254 for(size_t i = blocks; i != length; ++i)
255 {
256 out[i] ^= in[i];
257 }
258 }
259
260 /**
261 * XOR arrays. Postcondition out[i] = in[i] ^ in2[i] forall i = 0...length
262 * @param out the output buffer
263 * @param in the first input buffer
264 * @param in2 the second output buffer
265 * @param length the length of the three buffers
266 */
267 inline void xor_buf(uint8_t out[],
268 const uint8_t in[],
269 const uint8_t in2[],
270 size_t length)
271 {
272 const size_t blocks = length - (length % 32);
273
274 for(size_t i = 0; i != blocks; i += 32)
275 {
276 uint64_t x[4];
277 uint64_t y[4];
278
279 typecast_copy(x, in + i, 4);
280 typecast_copy(y, in2 + i, 4);
281
282 x[0] ^= y[0];
283 x[1] ^= y[1];
284 x[2] ^= y[2];
285 x[3] ^= y[3];
286
287 typecast_copy(out + i, x, 4);
288 }
289
290 for(size_t i = blocks; i != length; ++i)
291 {
292 out[i] = in[i] ^ in2[i];
293 }
294 }
295
296 template<typename Alloc, typename Alloc2>
297 void xor_buf(std::vector<uint8_t, Alloc>& out,
298 const std::vector<uint8_t, Alloc2>& in,
299 size_t n)
300 {
301 xor_buf(out.data(), in.data(), n);
302 }
303
304 template<typename Alloc>
305 void xor_buf(std::vector<uint8_t, Alloc>& out,
306 const uint8_t* in,
307 size_t n)
308 {
309 xor_buf(out.data(), in, n);
310 }
311
312 template<typename Alloc, typename Alloc2>
313 void xor_buf(std::vector<uint8_t, Alloc>& out,
314 const uint8_t* in,
315 const std::vector<uint8_t, Alloc2>& in2,
316 size_t n)
317 {
318 xor_buf(out.data(), in, in2.data(), n);
319 }
320
321 template<typename Alloc, typename Alloc2>
322 std::vector<uint8_t, Alloc>&
323 operator^=(std::vector<uint8_t, Alloc>& out,
324 const std::vector<uint8_t, Alloc2>& in)
325 {
326 if(out.size() < in.size())
327 out.resize(in.size());
328
329 xor_buf(out.data(), in.data(), in.size());
330 return out;
331 }
332
333 }
334
335 #endif
Botan::clear_bytes
void clear_bytes(void *ptr, size_t bytes)
Definition: mem_ops.h:94
Botan::same_mem
bool same_mem(const T *p1, const T *p2, size_t n)
Definition: mem_ops.h:216
Botan::allocate_memory
BOTAN_MALLOC_FN void * allocate_memory(size_t elems, size_t elem_size)
Definition: mem_ops.cpp:18
Botan::clear_mem
void clear_mem(T *ptr, size_t n)
Definition: mem_ops.h:112
Botan::set_mem
void set_mem(uint8_t *ptr, size_t n, uint8_t val)
Definition: mem_ops.h:181
BOTAN_PUBLIC_API
#define BOTAN_PUBLIC_API(maj, min)
Definition: compiler.h:31
Botan::cast_char_ptr_to_uint8
const uint8_t * cast_char_ptr_to_uint8(const char *s)
Definition: mem_ops.h:189
Botan::constant_time_compare
bool constant_time_compare(const uint8_t x[], const uint8_t y[], size_t len)
Definition: mem_ops.h:82
type
MechanismType type
Definition: p11_mechanism.cpp:44
Botan::typecast_copy
void typecast_copy(uint8_t out[], T in[], size_t N)
Definition: mem_ops.h:144
BOTAN_MALLOC_FN
#define BOTAN_MALLOC_FN
Definition: compiler.h:94
Botan::xor_buf
void xor_buf(uint8_t out[], const uint8_t in[], size_t length)
Definition: mem_ops.h:232
Botan::ct_compare_u8
uint8_t ct_compare_u8(const uint8_t x[], const uint8_t y[], size_t len)
Definition: mem_ops.cpp:56
Botan::operator^=
std::vector< uint8_t, Alloc > & operator^=(std::vector< uint8_t, Alloc > &out, const std::vector< uint8_t, Alloc2 > &in)
Definition: mem_ops.h:323
Botan::deallocate_memory
void deallocate_memory(void *p, size_t elems, size_t elem_size)
Definition: mem_ops.cpp:34
Botan::copy_mem
void copy_mem(T *out, const T *in, size_t n)
Definition: mem_ops.h:132
Botan
Definition: alg_id.cpp:13
BOTAN_IS_TRIVIALLY_COPYABLE
#define BOTAN_IS_TRIVIALLY_COPYABLE(T)
Definition: mem_ops.h:123
Botan::Allocator_Initializer::Allocator_Initializer
Allocator_Initializer()
Definition: mem_ops.h:44
Botan::secure_scrub_memory
void secure_scrub_memory(void *ptr, size_t n)
Definition: os_utils.cpp:66
Botan::cast_uint8_ptr_to_char
const char * cast_uint8_ptr_to_char(const uint8_t *b)
Definition: mem_ops.h:194
BOTAN_ASSERT_IMPLICATION
#define BOTAN_ASSERT_IMPLICATION(expr1, expr2, msg)
Definition: assert.h:94
T
fe T
Definition: ge.cpp:37
Botan::initialize_allocator
void initialize_allocator()
Definition: mem_ops.cpp:49
Botan::Allocator_Initializer
Definition: mem_ops.h:41