00001
00002
00003
00004
00005
00006
00007
00008 #ifndef BOTAN_SECURE_MEMORY_BUFFERS_H__
00009 #define BOTAN_SECURE_MEMORY_BUFFERS_H__
00010
00011 #include <botan/allocate.h>
00012 #include <botan/mem_ops.h>
00013 #include <algorithm>
00014
00015 namespace Botan {
00016
00017
00018
00019
00020 template<typename T>
00021 class MemoryRegion
00022 {
00023 public:
00024
00025
00026
00027
00028
00029 u32bit size() const { return used; }
00030
00031
00032
00033
00034
00035 bool empty() const { return (used == 0); }
00036
00037
00038
00039
00040
00041 operator T* () { return buf; }
00042
00043
00044
00045
00046
00047 operator const T* () const { return buf; }
00048
00049
00050
00051
00052
00053 T* begin() { return buf; }
00054
00055
00056
00057
00058
00059 const T* begin() const { return buf; }
00060
00061
00062
00063
00064
00065 T* end() { return (buf + size()); }
00066
00067
00068
00069
00070
00071 const T* end() const { return (buf + size()); }
00072
00073
00074
00075
00076
00077 bool operator==(const MemoryRegion<T>& other) const
00078 {
00079 return (size() == other.size() &&
00080 same_mem(buf, other.buf, size()));
00081 }
00082
00083
00084
00085
00086
00087 bool operator<(const MemoryRegion<T>& other) const;
00088
00089
00090
00091
00092
00093
00094 bool operator!=(const MemoryRegion<T>& other) const
00095 { return (!(*this == other)); }
00096
00097
00098
00099
00100
00101
00102
00103 MemoryRegion<T>& operator=(const MemoryRegion<T>& other)
00104 { if(this != &other) set(other); return (*this); }
00105
00106
00107
00108
00109
00110
00111
00112
00113 void copy(const T in[], u32bit n)
00114 { copy(0, in, n); }
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125 void copy(u32bit off, const T in[], u32bit n)
00126 { copy_mem(buf + off, in, (n > size() - off) ? (size() - off) : n); }
00127
00128
00129
00130
00131
00132
00133
00134 void set(const T in[], u32bit n) { resize(n); copy(in, n); }
00135
00136
00137
00138
00139
00140
00141 void set(const MemoryRegion<T>& in) { set(in.begin(), in.size()); }
00142
00143
00144
00145
00146
00147
00148 void append(const T data[], u32bit n)
00149 { grow_to(size()+n); copy(size() - n, data, n); }
00150
00151
00152
00153
00154
00155 void append(T x) { append(&x, 1); }
00156
00157
00158
00159
00160
00161 void append(const MemoryRegion<T>& other)
00162 { append(other.begin(), other.size()); }
00163
00164
00165
00166
00167 void clear() { clear_mem(buf, allocated); }
00168
00169
00170
00171
00172 void destroy() { resize(0); }
00173
00174
00175
00176
00177
00178
00179 void resize(u32bit n);
00180
00181
00182
00183
00184
00185
00186
00187
00188 void grow_to(u32bit n);
00189
00190
00191
00192
00193 void swap(MemoryRegion<T>& other);
00194
00195 ~MemoryRegion() { deallocate(buf, allocated); }
00196 protected:
00197 MemoryRegion() { buf = 0; alloc = 0; used = allocated = 0; }
00198
00199
00200
00201
00202
00203 MemoryRegion(const MemoryRegion<T>& other)
00204 {
00205 buf = 0;
00206 used = allocated = 0;
00207 alloc = other.alloc;
00208 set(other.buf, other.used);
00209 }
00210
00211
00212
00213
00214
00215 void init(bool locking, u32bit length = 0)
00216 { alloc = Allocator::get(locking); resize(length); }
00217 private:
00218 T* allocate(u32bit n)
00219 {
00220 return static_cast<T*>(alloc->allocate(sizeof(T)*n));
00221 }
00222
00223 void deallocate(T* p, u32bit n)
00224 { if(alloc && p && n) alloc->deallocate(p, sizeof(T)*n); }
00225
00226 T* buf;
00227 u32bit used;
00228 u32bit allocated;
00229 Allocator* alloc;
00230 };
00231
00232
00233
00234
00235 template<typename T>
00236 void MemoryRegion<T>::resize(u32bit n)
00237 {
00238 if(n <= allocated) { clear(); used = n; return; }
00239 deallocate(buf, allocated);
00240 buf = allocate(n);
00241 allocated = used = n;
00242 }
00243
00244
00245
00246
00247 template<typename T>
00248 void MemoryRegion<T>::grow_to(u32bit n)
00249 {
00250 if(n > used && n <= allocated)
00251 {
00252 clear_mem(buf + used, n - used);
00253 used = n;
00254 return;
00255 }
00256 else if(n > allocated)
00257 {
00258 T* new_buf = allocate(n);
00259 copy_mem(new_buf, buf, used);
00260 deallocate(buf, allocated);
00261 buf = new_buf;
00262 allocated = used = n;
00263 }
00264 }
00265
00266
00267
00268
00269 template<typename T>
00270 bool MemoryRegion<T>::operator<(const MemoryRegion<T>& other) const
00271 {
00272 if(size() < other.size()) return true;
00273 if(size() > other.size()) return false;
00274
00275 for(u32bit j = 0; j != size(); j++)
00276 {
00277 if(buf[j] < other[j]) return true;
00278 if(buf[j] > other[j]) return false;
00279 }
00280
00281 return false;
00282 }
00283
00284
00285
00286
00287 template<typename T>
00288 void MemoryRegion<T>::swap(MemoryRegion<T>& x)
00289 {
00290 std::swap(buf, x.buf);
00291 std::swap(used, x.used);
00292 std::swap(allocated, x.allocated);
00293 std::swap(alloc, x.alloc);
00294 }
00295
00296
00297
00298
00299
00300 template<typename T>
00301 class MemoryVector : public MemoryRegion<T>
00302 {
00303 public:
00304 using MemoryRegion<T>::set;
00305 using MemoryRegion<T>::init;
00306 using MemoryRegion<T>::append;
00307
00308
00309
00310
00311
00312
00313 MemoryVector<T>& operator=(const MemoryRegion<T>& in)
00314 { if(this != &in) set(in); return (*this); }
00315
00316
00317
00318
00319
00320 MemoryVector(u32bit n = 0) { init(false, n); }
00321
00322
00323
00324
00325
00326
00327
00328 MemoryVector(const T in[], u32bit n)
00329 { init(false); set(in, n); }
00330
00331
00332
00333
00334 MemoryVector(const MemoryRegion<T>& in)
00335 { init(false); set(in); }
00336
00337
00338
00339
00340
00341
00342
00343 MemoryVector(const MemoryRegion<T>& in1, const MemoryRegion<T>& in2)
00344 { init(false); set(in1); append(in2); }
00345 };
00346
00347
00348
00349
00350
00351
00352
00353 template<typename T, u32bit INITIAL_LEN = 0>
00354 class SecureVector : public MemoryRegion<T>
00355 {
00356 public:
00357 using MemoryRegion<T>::copy;
00358 using MemoryRegion<T>::set;
00359 using MemoryRegion<T>::init;
00360 using MemoryRegion<T>::append;
00361
00362
00363
00364
00365
00366
00367 SecureVector<T>& operator=(const MemoryRegion<T>& in)
00368 { if(this != &in) set(in); return (*this); }
00369
00370
00371
00372
00373
00374 SecureVector(u32bit n = INITIAL_LEN)
00375 { init(true, n); }
00376
00377
00378
00379
00380
00381
00382
00383 SecureVector(const T in[], u32bit n)
00384 {
00385 init(true, INITIAL_LEN);
00386 if(INITIAL_LEN)
00387 copy(in, n);
00388 else
00389 set(in, n);
00390 }
00391
00392
00393
00394
00395
00396
00397 SecureVector(const MemoryRegion<T>& in)
00398 {
00399 init(true, INITIAL_LEN);
00400 if(INITIAL_LEN)
00401 copy(in, in.size());
00402 else
00403 set(in);
00404 }
00405
00406
00407
00408
00409
00410
00411
00412 SecureVector(const MemoryRegion<T>& in1, const MemoryRegion<T>& in2)
00413 { init(true); set(in1); append(in2); }
00414 };
00415
00416 }
00417
00418 #endif