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
15namespace Botan {
16
17/**
18* This class represents variable length memory buffers.
19*/
20template<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* 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 */
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 */
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*/
216template<typename T>
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*/
238template<typename T>
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*/
259template<typename T>
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*/
272template<typename T>
273class 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 */
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 */
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*/
327template<typename T>
328class 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 */
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 */
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
385template<typename T>
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
395template<typename T>
397 T in)
398 {
399 out.push_back(in);
400 return out;
401 }
402
403template<typename T, typename L>
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
413template<typename T, typename L>
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*/
427template<typename T>
429 {
430 clear_mem(&vec[0], vec.size());
431 }
432
433}
434
435namespace std {
436
437template<typename T>
439 {
440 x.swap(y);
441 }
442
443}
444
445#endif
virtual void deallocate(void *ptr, size_t n)=0
virtual void * allocate(size_t n)=0
static Allocator * get(bool locking)
Definition defalloc.cpp:90
const T * begin() const
Definition secmem.h:65
size_t size() const
Definition secmem.h:29
void push_back(T x)
Definition secmem.h:149
bool operator<(const MemoryRegion< T > &other) const
Definition secmem.h:239
bool empty() const
Definition secmem.h:35
bool operator!=(const MemoryRegion< T > &other) const
Definition secmem.h:100
void init(bool locking, size_t length=0)
Definition secmem.h:195
void copy(size_t off, const T in[], size_t n)
Definition secmem.h:140
MemoryRegion< T > & operator=(const MemoryRegion< T > &other)
Definition secmem.h:109
const T * end() const
Definition secmem.h:77
void resize(size_t n)
Definition secmem.h:217
void swap(MemoryRegion< T > &other)
Definition secmem.h:260
MemoryRegion(const MemoryRegion< T > &other)
Definition secmem.h:181
bool operator==(const MemoryRegion< T > &other) const
Definition secmem.h:83
void copy(const T in[], size_t n)
Definition secmem.h:126
MemoryVector(size_t n=0)
Definition secmem.h:295
MemoryVector(const T in[], size_t n)
Definition secmem.h:303
MemoryVector(const MemoryRegion< T > &in)
Definition secmem.h:313
MemoryVector< T > & operator=(const MemoryRegion< T > &in)
Definition secmem.h:281
SecureVector(size_t n=0)
Definition secmem.h:350
SecureVector(const MemoryRegion< T > &in)
Definition secmem.h:370
SecureVector(const T in[], size_t n)
Definition secmem.h:358
SecureVector< T > & operator=(const MemoryRegion< T > &other)
Definition secmem.h:336
void zeroise(MemoryRegion< T > &vec)
Definition secmem.h:428
void copy_mem(T *out, const T *in, size_t n)
Definition mem_ops.h:22
bool same_mem(const T *p1, const T *p2, size_t n)
Definition mem_ops.h:57
MemoryRegion< T > & operator+=(MemoryRegion< T > &out, const MemoryRegion< T > &in)
Definition secmem.h:386
void clear_mem(T *ptr, size_t n)
Definition mem_ops.h:32
Definition secmem.h:435
void swap(Botan::MemoryRegion< T > &x, Botan::MemoryRegion< T > &y)
Definition secmem.h:438