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