Botan  1.10.9
secmem.h
Go to the documentation of this file.
1 /*
2 * Secure Memory Buffers
3 * (C) 1999-2007 Jack Lloyd
4 *
5 * Distributed under the terms of the Botan license
6 */
7 
8 #ifndef BOTAN_SECURE_MEMORY_BUFFERS_H__
9 #define BOTAN_SECURE_MEMORY_BUFFERS_H__
10 
11 #include <botan/allocate.h>
12 #include <botan/mem_ops.h>
13 #include <algorithm>
14 
15 namespace Botan {
16 
17 /**
18 * This class represents variable length memory buffers.
19 */
20 template<typename T>
22  {
23  public:
24  /**
25  * Find out the size of the buffer, i.e. how many objects of type T it
26  * contains.
27  * @return size of the buffer
28  */
29  size_t size() const { return used; }
30 
31  /**
32  * Find out whether this buffer is empty.
33  * @return true if the buffer is empty, false otherwise
34  */
35  bool empty() const { return (used == 0); }
36 
37  /**
38  * Get a pointer to the first element in the buffer.
39  * @return pointer to the first element in the buffer
40  */
41  operator T* () { return buf; }
42 
43  /**
44  * Get a constant pointer to the first element in the buffer.
45  * @return constant pointer to the first element in the buffer
46  */
47  operator const T* () const { return buf; }
48 
49  /**
50  * Get a pointer to the first element in the buffer.
51  * @return pointer to the first element in the buffer
52  */
53  T* begin() { return buf; }
54 
55  /**
56  * Get a constant pointer to the first element in the buffer.
57  * @return constant pointer to the first element in the buffer
58  */
59  const T* begin() const { return buf; }
60 
61  /**
62  * Get a pointer to one past the last element in the buffer.
63  * @return pointer to one past the last element in the buffer
64  */
65  T* end() { return (buf + size()); }
66 
67  /**
68  * Get a const pointer to one past the last element in the buffer.
69  * @return const pointer to one past the last element in the buffer
70  */
71  const T* end() const { return (buf + size()); }
72 
73  /**
74  * Check two buffers for equality.
75  * @return true iff the content of both buffers is byte-wise equal
76  */
77  bool operator==(const MemoryRegion<T>& other) const
78  {
79  return (size() == other.size() &&
80  same_mem(buf, other.buf, size()));
81  }
82 
83  /**
84  * Compare two buffers
85  * @return true iff this is ordered before other
86  */
87  bool operator<(const MemoryRegion<T>& other) const;
88 
89  /**
90  * Check two buffers for inequality.
91  * @return false if the content of both buffers is byte-wise equal, true
92  * otherwise.
93  */
94  bool operator!=(const MemoryRegion<T>& other) const
95  { return (!(*this == other)); }
96 
97  /**
98  * Copy the contents of another buffer into this buffer.
99  * The former contents of *this are discarded.
100  * @param other the buffer to copy the contents from.
101  * @return reference to *this
102  */
104  {
105  if(this != &other)
106  {
107  this->resize(other.size());
108  this->copy(&other[0], other.size());
109  }
110  return (*this);
111  }
112 
113  /**
114  * Copy the contents of an array of objects of type T into this buffer.
115  * The former contents of *this are discarded.
116  * The length of *this must be at least n, otherwise memory errors occur.
117  * @param in the array to copy the contents from
118  * @param n the length of in
119  */
120  void copy(const T in[], size_t n)
121  {
122  copy_mem(buf, in, std::min(n, size()));
123  }
124 
125  /**
126  * Copy the contents of an array of objects of type T into this buffer.
127  * The former contents of *this are discarded.
128  * The length of *this must be at least n, otherwise memory errors occur.
129  * @param off the offset position inside this buffer to start inserting
130  * the copied bytes
131  * @param in the array to copy the contents from
132  * @param n the length of in
133  */
134  void copy(size_t off, const T in[], size_t n)
135  {
136  copy_mem(buf + off, in, std::min(n, size() - off));
137  }
138 
139  /**
140  * Append a single element.
141  * @param x the element to append
142  */
143  void push_back(T x)
144  {
145  resize(size() + 1);
146  buf[size()-1] = x;
147  }
148 
149  /**
150  * Reset this buffer to an empty buffer with size zero.
151  */
152  void clear() { resize(0); }
153 
154  /**
155  * Inserts or erases elements at the end such that the size
156  * becomes n, leaving elements in the range 0...n unmodified if
157  * set or otherwise zero-initialized
158  * @param n length of the new buffer
159  */
160  void resize(size_t n);
161 
162  /**
163  * Swap this buffer with another object.
164  */
165  void swap(MemoryRegion<T>& other);
166 
167  ~MemoryRegion() { deallocate(buf, allocated); }
168  protected:
169  MemoryRegion() : buf(0), used(0), allocated(0), alloc(0) {}
170 
171  /**
172  * Copy constructor
173  * @param other the other region to copy
174  */
176  buf(0),
177  used(0),
178  allocated(0),
179  alloc(other.alloc)
180  {
181  resize(other.size());
182  copy(&other[0], other.size());
183  }
184 
185  /**
186  * @param locking should we use a locking allocator
187  * @param length the initial length to use
188  */
189  void init(bool locking, size_t length = 0)
190  { alloc = Allocator::get(locking); resize(length); }
191 
192  private:
193  T* allocate(size_t n)
194  {
195  return static_cast<T*>(alloc->allocate(sizeof(T)*n));
196  }
197 
198  void deallocate(T* p, size_t n)
199  { if(alloc && p && n) alloc->deallocate(p, sizeof(T)*n); }
200 
201  T* buf;
202  size_t used;
203  size_t allocated;
204  Allocator* alloc;
205  };
206 
207 /*
208 * Change the size of the buffer
209 */
210 template<typename T>
212  {
213  if(n <= allocated)
214  {
215  size_t zap = std::min(used, n);
216  clear_mem(buf + zap, allocated - zap);
217  used = n;
218  }
219  else
220  {
221  T* new_buf = allocate(n);
222  copy_mem(new_buf, buf, used);
223  deallocate(buf, allocated);
224  buf = new_buf;
225  allocated = used = n;
226  }
227  }
228 
229 /*
230 * Compare this buffer with another one
231 */
232 template<typename T>
234  {
235  const size_t min_size = std::min(size(), other.size());
236 
237  // This should probably be rewritten to run in constant time
238  for(size_t i = 0; i != min_size; ++i)
239  {
240  if(buf[i] < other[i])
241  return true;
242  if(buf[i] > other[i])
243  return false;
244  }
245 
246  // First min_size bytes are equal, shorter is first
247  return (size() < other.size());
248  }
249 
250 /*
251 * Swap this buffer with another one
252 */
253 template<typename T>
255  {
256  std::swap(buf, x.buf);
257  std::swap(used, x.used);
258  std::swap(allocated, x.allocated);
259  std::swap(alloc, x.alloc);
260  }
261 
262 /**
263 * This class represents variable length buffers that do not
264 * make use of memory locking.
265 */
266 template<typename T>
267 class MemoryVector : public MemoryRegion<T>
268  {
269  public:
270  /**
271  * Copy the contents of another buffer into this buffer.
272  * @param in the buffer to copy the contents from
273  * @return reference to *this
274  */
276  {
277  if(this != &in)
278  {
279  this->resize(in.size());
280  this->copy(&in[0], in.size());
281  }
282  return (*this);
283  }
284 
285  /**
286  * Create a buffer of the specified length.
287  * @param n the length of the buffer to create.
288  */
289  MemoryVector(size_t n = 0) { this->init(false, n); }
290 
291  /**
292  * Create a buffer with the specified contents.
293  * @param in the array containing the data to be initially copied
294  * into the newly created buffer
295  * @param n the size of the arry in
296  */
297  MemoryVector(const T in[], size_t n)
298  {
299  this->init(false);
300  this->resize(n);
301  this->copy(in, n);
302  }
303 
304  /**
305  * Copy constructor.
306  */
308  {
309  this->init(false);
310  this->resize(in.size());
311  this->copy(&in[0], in.size());
312  }
313  };
314 
315 /**
316 * This class represents variable length buffers using the operating
317 * systems capability to lock memory, i.e. keeping it from being
318 * swapped out to disk. In this way, a security hole allowing attackers
319 * to find swapped out secret keys is closed.
320 */
321 template<typename T>
322 class SecureVector : public MemoryRegion<T>
323  {
324  public:
325  /**
326  * Copy the contents of another buffer into this buffer.
327  * @param other the buffer to copy the contents from
328  * @return reference to *this
329  */
331  {
332  if(this != &other)
333  {
334  this->resize(other.size());
335  this->copy(&other[0], other.size());
336  }
337  return (*this);
338  }
339 
340  /**
341  * Create a buffer of the specified length.
342  * @param n the length of the buffer to create.
343  */
344  SecureVector(size_t n = 0) { this->init(true, n); }
345 
346  /**
347  * Create a buffer with the specified contents.
348  * @param in the array containing the data to be initially copied
349  * into the newly created buffer
350  * @param n the size of the array in
351  */
352  SecureVector(const T in[], size_t n)
353  {
354  this->init(true);
355  this->resize(n);
356  this->copy(&in[0], n);
357  }
358 
359  /**
360  * Create a buffer with contents specified contents.
361  * @param in the buffer holding the contents that will be
362  * copied into the newly created buffer.
363  */
365  {
366  this->init(true);
367  this->resize(in.size());
368  this->copy(&in[0], in.size());
369  }
370  };
371 
372 template<typename T>
374  const MemoryRegion<T>& in)
375  {
376  const size_t copy_offset = out.size();
377  out.resize(out.size() + in.size());
378  copy_mem(&out[copy_offset], &in[0], in.size());
379  return out;
380  }
381 
382 template<typename T>
384  T in)
385  {
386  out.push_back(in);
387  return out;
388  }
389 
390 template<typename T, typename L>
392  const std::pair<const T*, L>& in)
393  {
394  const size_t copy_offset = out.size();
395  out.resize(out.size() + in.second);
396  copy_mem(&out[copy_offset], in.first, in.second);
397  return out;
398  }
399 
400 template<typename T, typename L>
402  const std::pair<T*, L>& in)
403  {
404  const size_t copy_offset = out.size();
405  out.resize(out.size() + in.second);
406  copy_mem(&out[copy_offset], in.first, in.second);
407  return out;
408  }
409 
410 /**
411 * Zeroise the values; length remains unchanged
412 * @param vec the vector to zeroise
413 */
414 template<typename T>
416  {
417  clear_mem(&vec[0], vec.size());
418  }
419 
420 }
421 
422 namespace std {
423 
424 template<typename T>
426  {
427  x.swap(y);
428  }
429 
430 }
431 
432 #endif
void resize(size_t n)
Definition: secmem.h:211
virtual void deallocate(void *ptr, size_t n)=0
BigInt n
Definition: numthry.cpp:26
bool same_mem(const T *p1, const T *p2, size_t n)
Definition: mem_ops.h:57
SecureVector(const T in[], size_t n)
Definition: secmem.h:352
virtual void * allocate(size_t n)=0
void clear_mem(T *ptr, size_t n)
Definition: mem_ops.h:32
MemoryRegion< T > & operator=(const MemoryRegion< T > &other)
Definition: secmem.h:103
Definition: secmem.h:422
void push_back(T x)
Definition: secmem.h:143
static Allocator * get(bool locking)
Definition: defalloc.cpp:90
void copy(const T in[], size_t n)
Definition: secmem.h:120
void init(bool locking, size_t length=0)
Definition: secmem.h:189
SecureVector< T > & operator=(const MemoryRegion< T > &other)
Definition: secmem.h:330
const T * begin() const
Definition: secmem.h:59
MemoryVector(size_t n=0)
Definition: secmem.h:289
MemoryVector(const MemoryRegion< T > &in)
Definition: secmem.h:307
MemoryVector< T > & operator=(const MemoryRegion< T > &in)
Definition: secmem.h:275
SecureVector(size_t n=0)
Definition: secmem.h:344
bool operator==(const MemoryRegion< T > &other) const
Definition: secmem.h:77
bool empty() const
Definition: secmem.h:35
MemoryVector(const T in[], size_t n)
Definition: secmem.h:297
SecureVector(const MemoryRegion< T > &in)
Definition: secmem.h:364
size_t size() const
Definition: secmem.h:29
void copy_mem(T *out, const T *in, size_t n)
Definition: mem_ops.h:22
MemoryRegion< T > & operator+=(MemoryRegion< T > &out, const MemoryRegion< T > &in)
Definition: secmem.h:373
const T * end() const
Definition: secmem.h:71
void swap(MemoryRegion< T > &other)
Definition: secmem.h:254
void swap(Botan::MemoryRegion< T > &x, Botan::MemoryRegion< T > &y)
Definition: secmem.h:425
void copy(size_t off, const T in[], size_t n)
Definition: secmem.h:134
bool operator<(const MemoryRegion< T > &other) const
Definition: secmem.h:233
MemoryRegion(const MemoryRegion< T > &other)
Definition: secmem.h:175
Allocator * alloc
Definition: bzip2.cpp:29
void zeroise(MemoryRegion< T > &vec)
Definition: secmem.h:415
bool operator!=(const MemoryRegion< T > &other) const
Definition: secmem.h:94