Botan  2.8.0
Crypto and TLS for C++11
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 <vector>
14 
15 namespace Botan {
16 
17 /**
18 * Allocate a memory buffer by some method. This should only be used for
19 * primitive types (uint8_t, uint32_t, etc).
20 *
21 * @param elems the number of elements
22 * @param elem_size the size of each element
23 * @return pointer to allocated and zeroed memory, or throw std::bad_alloc on failure
24 */
25 BOTAN_PUBLIC_API(2,3) BOTAN_MALLOC_FN void* allocate_memory(size_t elems, size_t elem_size);
26 
27 /**
28 * Free a pointer returned by allocate_memory
29 * @param p the pointer returned by allocate_memory
30 * @param elems the number of elements, as passed to allocate_memory
31 * @param elem_size the size of each element, as passed to allocate_memory
32 */
33 BOTAN_PUBLIC_API(2,3) void deallocate_memory(void* p, size_t elems, size_t elem_size);
34 
35 /**
36 * Ensure the allocator is initialized
37 */
39 
41  {
42  public:
44  };
45 
46 /**
47 * Scrub memory contents in a way that a compiler should not elide,
48 * using some system specific technique. Note that this function might
49 * not zero the memory (for example, in some hypothetical
50 * implementation it might combine the memory contents with the output
51 * of a system PRNG), but if you can detect any difference in behavior
52 * at runtime then the clearing is side-effecting and you can just
53 * use `clear_mem`.
54 *
55 * Use this function to scrub memory just before deallocating it, or on
56 * a stack buffer before returning from the function.
57 *
58 * @param ptr a pointer to memory to scrub
59 * @param n the number of bytes pointed to by ptr
60 */
61 BOTAN_PUBLIC_API(2,0) void secure_scrub_memory(void* ptr, size_t n);
62 
63 /**
64 * Memory comparison, input insensitive
65 * @param x a pointer to an array
66 * @param y a pointer to another array
67 * @param len the number of Ts in x and y
68 * @return true iff x[i] == y[i] forall i in [0...n)
69 */
70 BOTAN_PUBLIC_API(2,3) bool constant_time_compare(const uint8_t x[],
71  const uint8_t y[],
72  size_t len);
73 
74 /**
75 * Zero out some bytes
76 * @param ptr a pointer to memory to zero
77 * @param bytes the number of bytes to zero in ptr
78 */
79 inline void clear_bytes(void* ptr, size_t bytes)
80  {
81  if(bytes > 0)
82  {
83  std::memset(ptr, 0, bytes);
84  }
85  }
86 
87 /**
88 * Zero memory before use. This simply calls memset and should not be
89 * used in cases where the compiler cannot see the call as a
90 * side-effecting operation (for example, if calling clear_mem before
91 * deallocating memory, the compiler would be allowed to omit the call
92 * to memset entirely under the as-if rule.)
93 *
94 * @param ptr a pointer to an array of Ts to zero
95 * @param n the number of Ts pointed to by ptr
96 */
97 template<typename T> inline void clear_mem(T* ptr, size_t n)
98  {
99  clear_bytes(ptr, sizeof(T)*n);
100  }
101 
102 /**
103 * Copy memory
104 * @param out the destination array
105 * @param in the source array
106 * @param n the number of elements of in/out
107 */
108 template<typename T> inline void copy_mem(T* out, const T* in, size_t n)
109  {
110  if(n > 0)
111  {
112  std::memmove(out, in, sizeof(T)*n);
113  }
114  }
115 
116 /**
117 * Set memory to a fixed value
118 * @param ptr a pointer to an array
119 * @param n the number of Ts pointed to by ptr
120 * @param val the value to set each byte to
121 */
122 template<typename T>
123 inline void set_mem(T* ptr, size_t n, uint8_t val)
124  {
125  if(n > 0)
126  {
127  std::memset(ptr, val, sizeof(T)*n);
128  }
129  }
130 
131 inline const uint8_t* cast_char_ptr_to_uint8(const char* s)
132  {
133  return reinterpret_cast<const uint8_t*>(s);
134  }
135 
136 inline const char* cast_uint8_ptr_to_char(const uint8_t* b)
137  {
138  return reinterpret_cast<const char*>(b);
139  }
140 
141 inline uint8_t* cast_char_ptr_to_uint8(char* s)
142  {
143  return reinterpret_cast<uint8_t*>(s);
144  }
145 
146 inline char* cast_uint8_ptr_to_char(uint8_t* b)
147  {
148  return reinterpret_cast<char*>(b);
149  }
150 
151 /**
152 * Memory comparison, input insensitive
153 * @param p1 a pointer to an array
154 * @param p2 a pointer to another array
155 * @param n the number of Ts in p1 and p2
156 * @return true iff p1[i] == p2[i] forall i in [0...n)
157 */
158 template<typename T> inline bool same_mem(const T* p1, const T* p2, size_t n)
159  {
160  volatile T difference = 0;
161 
162  for(size_t i = 0; i != n; ++i)
163  difference |= (p1[i] ^ p2[i]);
164 
165  return difference == 0;
166  }
167 
168 /**
169 * XOR arrays. Postcondition out[i] = in[i] ^ out[i] forall i = 0...length
170 * @param out the input/output buffer
171 * @param in the read-only input buffer
172 * @param length the length of the buffers
173 */
174 inline void xor_buf(uint8_t out[],
175  const uint8_t in[],
176  size_t length)
177  {
178  while(length >= 16)
179  {
180  uint64_t x0, x1, y0, y1;
181  std::memcpy(&x0, in, 8);
182  std::memcpy(&x1, in + 8, 8);
183  std::memcpy(&y0, out, 8);
184  std::memcpy(&y1, out + 8, 8);
185 
186  y0 ^= x0;
187  y1 ^= x1;
188  std::memcpy(out, &y0, 8);
189  std::memcpy(out + 8, &y1, 8);
190  out += 16; in += 16; length -= 16;
191  }
192 
193  while(length > 0)
194  {
195  out[0] ^= in[0];
196  out += 1;
197  in += 1;
198  length -= 1;
199  }
200  }
201 
202 /**
203 * XOR arrays. Postcondition out[i] = in[i] ^ in2[i] forall i = 0...length
204 * @param out the output buffer
205 * @param in the first input buffer
206 * @param in2 the second output buffer
207 * @param length the length of the three buffers
208 */
209 inline void xor_buf(uint8_t out[],
210  const uint8_t in[],
211  const uint8_t in2[],
212  size_t length)
213  {
214  while(length >= 16)
215  {
216  uint64_t x0, x1, y0, y1;
217  std::memcpy(&x0, in, 8);
218  std::memcpy(&x1, in + 8, 8);
219  std::memcpy(&y0, in2, 8);
220  std::memcpy(&y1, in2 + 8, 8);
221 
222  x0 ^= y0;
223  x1 ^= y1;
224  std::memcpy(out, &x0, 8);
225  std::memcpy(out + 8, &x1, 8);
226  out += 16; in += 16; in2 += 16; length -= 16;
227  }
228 
229  for(size_t i = 0; i != length; ++i)
230  out[i] = in[i] ^ in2[i];
231  }
232 
233 template<typename Alloc, typename Alloc2>
234 void xor_buf(std::vector<uint8_t, Alloc>& out,
235  const std::vector<uint8_t, Alloc2>& in,
236  size_t n)
237  {
238  xor_buf(out.data(), in.data(), n);
239  }
240 
241 template<typename Alloc>
242 void xor_buf(std::vector<uint8_t, Alloc>& out,
243  const uint8_t* in,
244  size_t n)
245  {
246  xor_buf(out.data(), in, n);
247  }
248 
249 template<typename Alloc, typename Alloc2>
250 void xor_buf(std::vector<uint8_t, Alloc>& out,
251  const uint8_t* in,
252  const std::vector<uint8_t, Alloc2>& in2,
253  size_t n)
254  {
255  xor_buf(out.data(), in, in2.data(), n);
256  }
257 
258 template<typename Alloc, typename Alloc2>
259 std::vector<uint8_t, Alloc>&
260 operator^=(std::vector<uint8_t, Alloc>& out,
261  const std::vector<uint8_t, Alloc2>& in)
262  {
263  if(out.size() < in.size())
264  out.resize(in.size());
265 
266  xor_buf(out.data(), in.data(), in.size());
267  return out;
268  }
269 
270 }
271 
272 #endif
void clear_bytes(void *ptr, size_t bytes)
Definition: mem_ops.h:79
bool same_mem(const T *p1, const T *p2, size_t n)
Definition: mem_ops.h:158
BOTAN_MALLOC_FN void * allocate_memory(size_t elems, size_t elem_size)
Definition: mem_ops.cpp:16
void clear_mem(T *ptr, size_t n)
Definition: mem_ops.h:97
#define BOTAN_PUBLIC_API(maj, min)
Definition: compiler.h:27
const uint8_t * cast_char_ptr_to_uint8(const char *s)
Definition: mem_ops.h:131
bool constant_time_compare(const uint8_t x[], const uint8_t y[], size_t len)
Definition: mem_ops.cpp:51
void set_mem(T *ptr, size_t n, uint8_t val)
Definition: mem_ops.h:123
#define BOTAN_MALLOC_FN
Definition: compiler.h:95
void xor_buf(uint8_t out[], const uint8_t in[], size_t length)
Definition: mem_ops.h:174
std::vector< uint8_t, Alloc > & operator^=(std::vector< uint8_t, Alloc > &out, const std::vector< uint8_t, Alloc2 > &in)
Definition: mem_ops.h:260
void deallocate_memory(void *p, size_t elems, size_t elem_size)
Definition: mem_ops.cpp:29
void copy_mem(T *out, const T *in, size_t n)
Definition: mem_ops.h:108
Definition: alg_id.cpp:13
void secure_scrub_memory(void *ptr, size_t n)
Definition: os_utils.cpp:43
const char * cast_uint8_ptr_to_char(const uint8_t *b)
Definition: mem_ops.h:136
fe T
Definition: ge.cpp:37
void initialize_allocator()
Definition: mem_ops.cpp:44