Botan 1.10.17

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