2
* Secure Memory Buffers
3
* (C) 1999-2007 Jack Lloyd
5
* Distributed under the terms of the Botan license
8
#ifndef BOTAN_SECURE_MEMORY_BUFFERS_H__
9
#define BOTAN_SECURE_MEMORY_BUFFERS_H__
11
#include <botan/allocate.h>
12
#include <botan/mem_ops.h>
18
* This class represents variable length memory buffers.
25
* Find out the size of the buffer, i.e. how many objects of type T it
27
* @return the size of the buffer
29
u32bit size() const { return used; }
32
* Find out whether this buffer is empty.
33
* @return true if the buffer is empty, false otherwise
35
bool is_empty() const { return (used == 0); }
38
* Find out whether this buffer is non-empty
39
* @return true if the buffer is non-empty, false otherwise
41
bool has_items() const { return (used != 0); }
44
* Get a pointer to the first element in the buffer.
45
* @return a pointer to the first element in the buffer
47
operator T* () { return buf; }
50
* Get a constant pointer to the first element in the buffer.
51
* @return a constant pointer to the first element in the buffer
53
operator const T* () const { return buf; }
56
* Get a pointer to the first element in the buffer.
57
* @return a pointer to the first element in the buffer
59
T* begin() { return buf; }
62
* Get a constant pointer to the first element in the buffer.
63
* @return a constant pointer to the first element in the buffer
65
const T* begin() const { return buf; }
68
* Get a pointer to the last element in the buffer.
69
* @return a pointer to the last element in the buffer
71
T* end() { return (buf + size()); }
74
* Get a constant pointer to the last element in the buffer.
75
* @return a constant pointer to the last element in the buffer
77
const T* end() const { return (buf + size()); }
80
* Check two buffers for equality.
81
* @return true iff the content of both buffers is byte-wise equal
83
bool operator==(const MemoryRegion<T>& other) const
85
return (size() == other.size() &&
86
same_mem(buf, other.buf, size()));
90
* Compare two buffers lexicographically.
91
* @return true if this buffer is lexicographically smaller than other.
93
bool operator<(const MemoryRegion<T>& other) const;
96
* Check two buffers for inequality.
97
* @return false if the content of both buffers is byte-wise equal, true
100
bool operator!=(const MemoryRegion<T>& in) const
101
{ return (!(*this == in)); }
104
* Copy the contents of another buffer into this buffer.
105
* The former contents of *this are discarded.
106
* @param in the buffer to copy the contents from.
107
* @return a reference to *this
109
MemoryRegion<T>& operator=(const MemoryRegion<T>& in)
110
{ if(this != &in) set(in); return (*this); }
113
* The use of this function is discouraged because of the risk of memory
114
* errors. Use MemoryRegion<T>::set()
116
* Copy the contents of an array of objects of type T into this buffer.
117
* The former contents of *this are discarded.
118
* The length of *this must be at least n, otherwise memory errors occur.
119
* @param in the array to copy the contents from
120
* @param n the length of in
122
void copy(const T in[], u32bit n)
126
* The use of this function is discouraged because of the risk of memory
127
* errors. Use MemoryRegion<T>::set()
129
* Copy the contents of an array of objects of type T into this buffer.
130
* The former contents of *this are discarded.
131
* The length of *this must be at least n, otherwise memory errors occur.
132
* @param off the offset position inside this buffer to start inserting
134
* @param in the array to copy the contents from
135
* @param n the length of in
137
void copy(u32bit off, const T in[], u32bit n)
138
{ copy_mem(buf + off, in, (n > size() - off) ? (size() - off) : n); }
141
* Set the contents of this according to the argument. The size of
142
* *this is increased if necessary.
143
* @param in the array of objects of type T to copy the contents from
144
* @param n the size of array in
146
void set(const T in[], u32bit n) { create(n); copy(in, n); }
149
* Set the contents of this according to the argument. The size of
150
* *this is increased if necessary.
151
* @param in the buffer to copy the contents from
153
void set(const MemoryRegion<T>& in) { set(in.begin(), in.size()); }
156
* Append data to the end of this buffer.
157
* @param data the array containing the data to append
158
* @param n the size of the array data
160
void append(const T data[], u32bit n)
161
{ grow_to(size()+n); copy(size() - n, data, n); }
164
* Append a single element.
165
* @param x the element to append
167
void append(T x) { append(&x, 1); }
170
* Append data to the end of this buffer.
171
* @param data the buffer containing the data to append
173
void append(const MemoryRegion<T>& x) { append(x.begin(), x.size()); }
176
* Zeroise the bytes of this buffer. The length remains unchanged.
178
void clear() { clear_mem(buf, allocated); }
181
* Reset this buffer to an empty buffer with size zero.
183
void destroy() { create(0); }
186
* Reset this buffer to a buffer of specified length. The content will be
187
* initialized to zero bytes.
188
* @param n the new length of the buffer
190
void create(u32bit n);
193
* Preallocate memory, so that this buffer can grow up to size n without
194
* having to perform any actual memory allocations. (This is
195
* the same principle as for std::vector::reserve().)
197
void grow_to(u32bit N);
200
* Swap this buffer with another object.
202
void swap(MemoryRegion<T>& other);
204
~MemoryRegion() { deallocate(buf, allocated); }
206
MemoryRegion() { buf = 0; alloc = 0; used = allocated = 0; }
207
MemoryRegion(const MemoryRegion<T>& other)
210
used = allocated = 0;
212
set(other.buf, other.used);
215
void init(bool locking, u32bit length = 0)
216
{ alloc = Allocator::get(locking); create(length); }
218
T* allocate(u32bit n)
220
return static_cast<T*>(alloc->allocate(sizeof(T)*n));
223
void deallocate(T* p, u32bit n)
224
{ alloc->deallocate(p, sizeof(T)*n); }
233
* Create a new buffer
236
void MemoryRegion<T>::create(u32bit n)
238
if(n <= allocated) { clear(); used = n; return; }
239
deallocate(buf, allocated);
241
allocated = used = n;
245
* Increase the size of the buffer
248
void MemoryRegion<T>::grow_to(u32bit n)
250
if(n > used && n <= allocated)
252
clear_mem(buf + used, n - used);
256
else if(n > allocated)
258
T* new_buf = allocate(n);
259
copy_mem(new_buf, buf, used);
260
deallocate(buf, allocated);
262
allocated = used = n;
267
* Compare this buffer with another one
270
bool MemoryRegion<T>::operator<(const MemoryRegion<T>& in) const
272
if(size() < in.size()) return true;
273
if(size() > in.size()) return false;
275
for(u32bit j = 0; j != size(); j++)
277
if(buf[j] < in[j]) return true;
278
if(buf[j] > in[j]) return false;
285
* Swap this buffer with another one
288
void MemoryRegion<T>::swap(MemoryRegion<T>& x)
290
std::swap(buf, x.buf);
291
std::swap(used, x.used);
292
std::swap(allocated, x.allocated);
293
std::swap(alloc, x.alloc);
297
* This class represents variable length buffers that do not
298
* make use of memory locking.
301
class MemoryVector : public MemoryRegion<T>
305
* Copy the contents of another buffer into this buffer.
306
* @param in the buffer to copy the contents from
307
* @return a reference to *this
309
MemoryVector<T>& operator=(const MemoryRegion<T>& in)
310
{ if(this != &in) set(in); return (*this); }
313
* Create a buffer of the specified length.
314
* @param n the length of the buffer to create.
317
MemoryVector(u32bit n = 0) { MemoryRegion<T>::init(false, n); }
320
* Create a buffer with the specified contents.
321
* @param in the array containing the data to be initially copied
322
* into the newly created buffer
323
* @param n the size of the arry in
325
MemoryVector(const T in[], u32bit n)
326
{ MemoryRegion<T>::init(false); set(in, n); }
331
MemoryVector(const MemoryRegion<T>& in)
332
{ MemoryRegion<T>::init(false); set(in); }
335
* Create a buffer whose content is the concatenation of two other
337
* @param in1 the first part of the new contents
338
* @param in2 the contents to be appended to in1
340
MemoryVector(const MemoryRegion<T>& in1, const MemoryRegion<T>& in2)
341
{ MemoryRegion<T>::init(false); set(in1); append(in2); }
345
* This class represents variable length buffers using the operating
346
* systems capability to lock memory, i.e. keeping it from being
347
* swapped out to disk. In this way, a security hole allowing attackers
348
* to find swapped out secret keys is closed. Please refer to
349
* Botan::InitializerOptions::secure_memory() for restrictions and
353
class SecureVector : public MemoryRegion<T>
357
* Copy the contents of another buffer into this buffer.
358
* @param in the buffer to copy the contents from
359
* @return a reference to *this
361
SecureVector<T>& operator=(const MemoryRegion<T>& in)
362
{ if(this != &in) set(in); return (*this); }
365
* Create a buffer of the specified length.
366
* @param n the length of the buffer to create.
369
SecureVector(u32bit n = 0) { MemoryRegion<T>::init(true, n); }
372
* Create a buffer with the specified contents.
373
* @param in the array containing the data to be initially copied
374
* into the newly created buffer
375
* @param n the size of the array in
377
SecureVector(const T in[], u32bit n)
378
{ MemoryRegion<T>::init(true); set(in, n); }
381
* Create a buffer with contents specified contents.
382
* @param in the buffer holding the contents that will be
383
* copied into the newly created buffer.
385
SecureVector(const MemoryRegion<T>& in)
386
{ MemoryRegion<T>::init(true); set(in); }
389
* Create a buffer whose content is the concatenation of two other
391
* @param in1 the first part of the new contents
392
* @param in2 the contents to be appended to in1
394
SecureVector(const MemoryRegion<T>& in1, const MemoryRegion<T>& in2)
395
{ MemoryRegion<T>::init(true); set(in1); append(in2); }
399
* This class represents fixed length buffers using the operating
400
* systems capability to lock memory, i.e. keeping it from being
401
* swapped out to disk. In this way, a security hole allowing attackers
402
* to find swapped out secret keys is closed. Please refer to
403
* Botan::InitializerOptions::secure_memory() for restrictions and
406
template<typename T, u32bit L>
407
class SecureBuffer : public MemoryRegion<T>
411
* Copy the contents of another buffer into this buffer.
412
* @param in the buffer to copy the contents from
413
* @return a reference to *this
415
SecureBuffer<T,L>& operator=(const SecureBuffer<T,L>& in)
416
{ if(this != &in) set(in); return (*this); }
419
* Create a buffer of the length L.
421
SecureBuffer() { MemoryRegion<T>::init(true, L); }
424
* Create a buffer of size L with the specified contents.
425
* @param in the array containing the data to be initially copied
426
* into the newly created buffer
427
* @param n the size of the array in
429
SecureBuffer(const T in[], u32bit n)
430
{ MemoryRegion<T>::init(true, L); copy(in, n); }
432
SecureBuffer<T, L>& operator=(const MemoryRegion<T>& in)
433
{ if(this != &in) set(in); return (*this); }