Botan: src/alloc/secmem.h Source File

Botan 1.10.16

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* 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 */
103 MemoryRegion<T>& operator=(const MemoryRegion<T>& other)
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 */
175 MemoryRegion(const MemoryRegion<T>& other) :
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>
211 void MemoryRegion<T>::resize(size_t n)
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>
233 bool MemoryRegion<T>::operator<(const MemoryRegion<T>& other) const
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>
254 void MemoryRegion<T>::swap(MemoryRegion<T>& x)
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 */
275 MemoryVector<T>& operator=(const MemoryRegion<T>& in)
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 */
307 MemoryVector(const MemoryRegion<T>& in)
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 */
330 SecureVector<T>& operator=(const MemoryRegion<T>& other)
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 */
364 SecureVector(const MemoryRegion<T>& in)
365 {
366 this->init(true);
367 this->resize(in.size());
368 this->copy(&in[0], in.size());
369 }
370 };
371
372 template<typename T>
373 MemoryRegion<T>& operator+=(MemoryRegion<T>& out,
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>
383 MemoryRegion<T>& operator+=(MemoryRegion<T>& out,
384 T in)
385 {
386 out.push_back(in);
387 return out;
388 }
389
390 template<typename T, typename L>
391 MemoryRegion<T>& operator+=(MemoryRegion<T>& out,
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>
401 MemoryRegion<T>& operator+=(MemoryRegion<T>& out,
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>
415 void zeroise(MemoryRegion<T>& vec)
416 {
417 clear_mem(&vec[0], vec.size());
418 }
419
420 }
421
422 namespace std {
423
424 template<typename T>
425 inline void swap(Botan::MemoryRegion<T>& x, Botan::MemoryRegion<T>& y)
426 {
427 x.swap(y);
428 }
429
430 }
431
432 #endif
Botan::MemoryRegion::~MemoryRegion
~MemoryRegion()
Definition: secmem.h:167
Botan::MemoryRegion::resize
void resize(size_t n)
Definition: secmem.h:211
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:352
Botan::MemoryRegion::end
const T * end() const
Definition: secmem.h:71
Botan::Allocator
Definition: allocate.h:19
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::operator=
MemoryRegion< T > & operator=(const MemoryRegion< T > &other)
Definition: secmem.h:103
Botan::MemoryRegion::clear
void clear()
Definition: secmem.h:152
std
Definition: secmem.h:422
Botan::MemoryRegion::push_back
void push_back(T x)
Definition: secmem.h:143
Botan::MemoryRegion::operator==
bool operator==(const MemoryRegion< T > &other) const
Definition: secmem.h:77
Botan::MemoryRegion::end
T * end()
Definition: secmem.h:65
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:94
Botan::MemoryRegion::begin
const T * begin() const
Definition: secmem.h:59
Botan::MemoryRegion::copy
void copy(const T in[], size_t n)
Definition: secmem.h:120
Botan::MemoryRegion::init
void init(bool locking, size_t length=0)
Definition: secmem.h:189
Botan::SecureVector::operator=
SecureVector< T > & operator=(const MemoryRegion< T > &other)
Definition: secmem.h:330
Botan::MemoryVector::MemoryVector
MemoryVector(size_t n=0)
Definition: secmem.h:289
Botan::MemoryRegion::empty
bool empty() const
Definition: secmem.h:35
Botan::MemoryVector::MemoryVector
MemoryVector(const MemoryRegion< T > &in)
Definition: secmem.h:307
Botan::MemoryVector::operator=
MemoryVector< T > & operator=(const MemoryRegion< T > &in)
Definition: secmem.h:275
Botan::SecureVector::SecureVector
SecureVector(size_t n=0)
Definition: secmem.h:344
Botan::MemoryVector::MemoryVector
MemoryVector(const T in[], size_t n)
Definition: secmem.h:297
Botan::SecureVector::SecureVector
SecureVector(const MemoryRegion< T > &in)
Definition: secmem.h:364
Botan::MemoryRegion::MemoryRegion
MemoryRegion()
Definition: secmem.h:169
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:373
Botan
Definition: algo_base.h:14
Botan::MemoryVector
Definition: secmem.h:267
Botan::MemoryRegion::size
size_t size() const
Definition: secmem.h:29
Botan::MemoryRegion::swap
void swap(MemoryRegion< T > &other)
Definition: secmem.h:254
Botan::MemoryRegion::begin
T * begin()
Definition: secmem.h:53
Botan::CT::min
T min(T a, T b)
Definition: ct_utils.h:127
Botan::SecureVector
Definition: secmem.h:322
std::swap
void swap(Botan::MemoryRegion< T > &x, Botan::MemoryRegion< T > &y)
Definition: secmem.h:425
Botan::MemoryRegion::copy
void copy(size_t off, const T in[], size_t n)
Definition: secmem.h:134
Botan::MemoryRegion::MemoryRegion
MemoryRegion(const MemoryRegion< T > &other)
Definition: secmem.h:175
Botan::zeroise
void zeroise(MemoryRegion< T > &vec)
Definition: secmem.h:415
Botan::MemoryRegion::operator<
bool operator<(const MemoryRegion< T > &other) const
Definition: secmem.h:233