~ubuntu-branches/ubuntu/precise/botan1.8/precise

« back to all changes in this revision

Viewing changes to src/alloc/secmem.h

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Baumann
  • Date: 2009-08-04 00:47:32 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20090804004732-bmf7f33nfoctocbz
Tags: 1.8.5-1
* Merging upstream version 1.8.5.
* Adding old changelog entries for separately uploaded botan packages
  in the past.
* Using correct rfc-2822 date formats in changelog.
* Wrapping build depends.
* Adding misc depends.
* Renaming local manpages directory to common name.
* Minimizing rules file.
* Doing some minor cosmetical updates in the manpage.
* Updating copyright file to reflect changes of upstream version
  1.8.0.
* Using new configure.py instread of configure.pl, updating necessary
  things to cope with that.
* Updating.
* Tidy debhelper install files.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 the size of the buffer
 
28
      */
 
29
      u32bit 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 is_empty() const { return (used == 0); }
 
36
 
 
37
      /**
 
38
      * Find out whether this buffer is non-empty
 
39
      * @return true if the buffer is non-empty, false otherwise
 
40
      */
 
41
      bool has_items() const { return (used != 0); }
 
42
 
 
43
      /**
 
44
      * Get a pointer to the first element in the buffer.
 
45
      * @return a pointer to the first element in the buffer
 
46
      */
 
47
      operator T* () { return buf; }
 
48
 
 
49
      /**
 
50
      * Get a constant pointer to the first element in the buffer.
 
51
      * @return a constant pointer to the first element in the buffer
 
52
      */
 
53
      operator const T* () const { return buf; }
 
54
 
 
55
      /**
 
56
      * Get a pointer to the first element in the buffer.
 
57
      * @return a 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 a constant pointer to the first element in the buffer
 
64
      */
 
65
      const T* begin() const { return buf; }
 
66
 
 
67
      /**
 
68
      * Get a pointer to the last element in the buffer.
 
69
      * @return a pointer to the last element in the buffer
 
70
      */
 
71
      T* end() { return (buf + size()); }
 
72
 
 
73
      /**
 
74
      * Get a constant pointer to the last element in the buffer.
 
75
      * @return a constant pointer to 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 lexicographically.
 
91
      * @return true if this buffer is lexicographically smaller than 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>& in) const
 
101
         { return (!(*this == in)); }
 
102
 
 
103
      /**
 
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
 
108
      */
 
109
      MemoryRegion<T>& operator=(const MemoryRegion<T>& in)
 
110
         { if(this != &in) set(in); return (*this); }
 
111
 
 
112
      /**
 
113
      * The use of this function is discouraged because of the risk of memory
 
114
      * errors. Use MemoryRegion<T>::set()
 
115
      * instead.
 
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
 
121
      */
 
122
      void copy(const T in[], u32bit n)
 
123
         { copy(0, in, n); }
 
124
 
 
125
      /**
 
126
      * The use of this function is discouraged because of the risk of memory
 
127
      * errors. Use MemoryRegion<T>::set()
 
128
      * instead.
 
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
 
133
      * the copied bytes
 
134
      * @param in the array to copy the contents from
 
135
      * @param n the length of in
 
136
      */
 
137
      void copy(u32bit off, const T in[], u32bit n)
 
138
         { copy_mem(buf + off, in, (n > size() - off) ? (size() - off) : n); }
 
139
 
 
140
      /**
 
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
 
145
      */
 
146
      void set(const T in[], u32bit n)    { create(n); copy(in, n); }
 
147
 
 
148
      /**
 
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
 
152
      */
 
153
      void set(const MemoryRegion<T>& in) { set(in.begin(), in.size()); }
 
154
 
 
155
      /**
 
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
 
159
      */
 
160
      void append(const T data[], u32bit n)
 
161
         { grow_to(size()+n); copy(size() - n, data, n); }
 
162
 
 
163
      /**
 
164
      * Append a single element.
 
165
      * @param x the element to append
 
166
      */
 
167
      void append(T x) { append(&x, 1); }
 
168
 
 
169
      /**
 
170
      * Append data to the end of this buffer.
 
171
      * @param data the buffer containing the data to append
 
172
      */
 
173
      void append(const MemoryRegion<T>& x) { append(x.begin(), x.size()); }
 
174
 
 
175
      /**
 
176
      * Zeroise the bytes of this buffer. The length remains unchanged.
 
177
      */
 
178
      void clear() { clear_mem(buf, allocated); }
 
179
 
 
180
      /**
 
181
      * Reset this buffer to an empty buffer with size zero.
 
182
      */
 
183
      void destroy() { create(0); }
 
184
 
 
185
      /**
 
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
 
189
      */
 
190
      void create(u32bit n);
 
191
 
 
192
      /**
 
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().)
 
196
      */
 
197
      void grow_to(u32bit N);
 
198
 
 
199
      /**
 
200
      * Swap this buffer with another object.
 
201
      */
 
202
      void swap(MemoryRegion<T>& other);
 
203
 
 
204
      ~MemoryRegion() { deallocate(buf, allocated); }
 
205
   protected:
 
206
      MemoryRegion() { buf = 0; alloc = 0; used = allocated = 0; }
 
207
      MemoryRegion(const MemoryRegion<T>& other)
 
208
         {
 
209
         buf = 0;
 
210
         used = allocated = 0;
 
211
         alloc = other.alloc;
 
212
         set(other.buf, other.used);
 
213
         }
 
214
 
 
215
      void init(bool locking, u32bit length = 0)
 
216
         { alloc = Allocator::get(locking); create(length); }
 
217
   private:
 
218
      T* allocate(u32bit n)
 
219
         {
 
220
         return static_cast<T*>(alloc->allocate(sizeof(T)*n));
 
221
         }
 
222
 
 
223
      void deallocate(T* p, u32bit n)
 
224
         { alloc->deallocate(p, sizeof(T)*n); }
 
225
 
 
226
      T* buf;
 
227
      u32bit used;
 
228
      u32bit allocated;
 
229
      Allocator* alloc;
 
230
   };
 
231
 
 
232
/*
 
233
* Create a new buffer
 
234
*/
 
235
template<typename T>
 
236
void MemoryRegion<T>::create(u32bit n)
 
237
   {
 
238
   if(n <= allocated) { clear(); used = n; return; }
 
239
   deallocate(buf, allocated);
 
240
   buf = allocate(n);
 
241
   allocated = used = n;
 
242
   }
 
243
 
 
244
/*
 
245
* Increase the size of the buffer
 
246
*/
 
247
template<typename T>
 
248
void MemoryRegion<T>::grow_to(u32bit n)
 
249
   {
 
250
   if(n > used && n <= allocated)
 
251
      {
 
252
      clear_mem(buf + used, n - used);
 
253
      used = n;
 
254
      return;
 
255
      }
 
256
   else if(n > allocated)
 
257
      {
 
258
      T* new_buf = allocate(n);
 
259
      copy_mem(new_buf, buf, used);
 
260
      deallocate(buf, allocated);
 
261
      buf = new_buf;
 
262
      allocated = used = n;
 
263
      }
 
264
   }
 
265
 
 
266
/*
 
267
* Compare this buffer with another one
 
268
*/
 
269
template<typename T>
 
270
bool MemoryRegion<T>::operator<(const MemoryRegion<T>& in) const
 
271
   {
 
272
   if(size() < in.size()) return true;
 
273
   if(size() > in.size()) return false;
 
274
 
 
275
   for(u32bit j = 0; j != size(); j++)
 
276
      {
 
277
      if(buf[j] < in[j]) return true;
 
278
      if(buf[j] > in[j]) return false;
 
279
      }
 
280
 
 
281
   return false;
 
282
   }
 
283
 
 
284
/*
 
285
* Swap this buffer with another one
 
286
*/
 
287
template<typename T>
 
288
void MemoryRegion<T>::swap(MemoryRegion<T>& x)
 
289
   {
 
290
   std::swap(buf, x.buf);
 
291
   std::swap(used, x.used);
 
292
   std::swap(allocated, x.allocated);
 
293
   std::swap(alloc, x.alloc);
 
294
   }
 
295
 
 
296
/**
 
297
* This class represents variable length buffers that do not
 
298
* make use of memory locking.
 
299
*/
 
300
template<typename T>
 
301
class MemoryVector : public MemoryRegion<T>
 
302
   {
 
303
   public:
 
304
      /**
 
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
 
308
      */
 
309
      MemoryVector<T>& operator=(const MemoryRegion<T>& in)
 
310
         { if(this != &in) set(in); return (*this); }
 
311
 
 
312
      /**
 
313
      * Create a buffer of the specified length.
 
314
      * @param n the length of the buffer to create.
 
315
 
 
316
      */
 
317
      MemoryVector(u32bit n = 0) { MemoryRegion<T>::init(false, n); }
 
318
 
 
319
      /**
 
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
 
324
      */
 
325
      MemoryVector(const T in[], u32bit n)
 
326
         { MemoryRegion<T>::init(false); set(in, n); }
 
327
 
 
328
      /**
 
329
      * Copy constructor.
 
330
      */
 
331
      MemoryVector(const MemoryRegion<T>& in)
 
332
         { MemoryRegion<T>::init(false); set(in); }
 
333
 
 
334
      /**
 
335
      * Create a buffer whose content is the concatenation of two other
 
336
      * buffers.
 
337
      * @param in1 the first part of the new contents
 
338
      * @param in2 the contents to be appended to in1
 
339
      */
 
340
      MemoryVector(const MemoryRegion<T>& in1, const MemoryRegion<T>& in2)
 
341
         { MemoryRegion<T>::init(false); set(in1); append(in2); }
 
342
   };
 
343
 
 
344
/**
 
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
 
350
* further details.
 
351
*/
 
352
template<typename T>
 
353
class SecureVector : public MemoryRegion<T>
 
354
   {
 
355
   public:
 
356
      /**
 
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
 
360
      */
 
361
      SecureVector<T>& operator=(const MemoryRegion<T>& in)
 
362
         { if(this != &in) set(in); return (*this); }
 
363
 
 
364
      /**
 
365
      * Create a buffer of the specified length.
 
366
      * @param n the length of the buffer to create.
 
367
 
 
368
      */
 
369
      SecureVector(u32bit n = 0) { MemoryRegion<T>::init(true, n); }
 
370
 
 
371
      /**
 
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
 
376
      */
 
377
      SecureVector(const T in[], u32bit n)
 
378
         { MemoryRegion<T>::init(true); set(in, n); }
 
379
 
 
380
      /**
 
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.
 
384
      */
 
385
      SecureVector(const MemoryRegion<T>& in)
 
386
         { MemoryRegion<T>::init(true); set(in); }
 
387
 
 
388
      /**
 
389
      * Create a buffer whose content is the concatenation of two other
 
390
      * buffers.
 
391
      * @param in1 the first part of the new contents
 
392
      * @param in2 the contents to be appended to in1
 
393
      */
 
394
      SecureVector(const MemoryRegion<T>& in1, const MemoryRegion<T>& in2)
 
395
         { MemoryRegion<T>::init(true); set(in1); append(in2); }
 
396
   };
 
397
 
 
398
/**
 
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
 
404
* further details.
 
405
*/
 
406
template<typename T, u32bit L>
 
407
class SecureBuffer : public MemoryRegion<T>
 
408
   {
 
409
   public:
 
410
      /**
 
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
 
414
      */
 
415
      SecureBuffer<T,L>& operator=(const SecureBuffer<T,L>& in)
 
416
         { if(this != &in) set(in); return (*this); }
 
417
 
 
418
      /**
 
419
      * Create a buffer of the length L.
 
420
      */
 
421
      SecureBuffer() { MemoryRegion<T>::init(true, L); }
 
422
 
 
423
      /**
 
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
 
428
      */
 
429
      SecureBuffer(const T in[], u32bit n)
 
430
         { MemoryRegion<T>::init(true, L); copy(in, n); }
 
431
   private:
 
432
      SecureBuffer<T, L>& operator=(const MemoryRegion<T>& in)
 
433
         { if(this != &in) set(in); return (*this); }
 
434
   };
 
435
 
 
436
}
 
437
 
 
438
#endif