00001
00002
00003 #ifndef CRYPTOPP_SECBLOCK_H
00004 #define CRYPTOPP_SECBLOCK_H
00005
00006 #include "config.h"
00007 #include "misc.h"
00008 #include <assert.h>
00009
00010 NAMESPACE_BEGIN(CryptoPP)
00011
00012
00013
00014 template<class T>
00015 class AllocatorBase
00016 {
00017 public:
00018 typedef T value_type;
00019 typedef size_t size_type;
00020 #ifdef CRYPTOPP_MSVCRT6
00021 typedef ptrdiff_t difference_type;
00022 #else
00023 typedef std::ptrdiff_t difference_type;
00024 #endif
00025 typedef T * pointer;
00026 typedef const T * const_pointer;
00027 typedef T & reference;
00028 typedef const T & const_reference;
00029
00030 pointer address(reference r) const {return (&r);}
00031 const_pointer address(const_reference r) const {return (&r); }
00032 void construct(pointer p, const T& val) {new (p) T(val);}
00033 void destroy(pointer p) {p->~T();}
00034 size_type max_size() const {return ~size_type(0)/sizeof(T);}
00035
00036 protected:
00037 static void CheckSize(size_t n)
00038 {
00039 if (n > ~size_t(0) / sizeof(T))
00040 throw InvalidArgument("AllocatorBase: requested size would cause integer overflow");
00041 }
00042 };
00043
00044 #define CRYPTOPP_INHERIT_ALLOCATOR_TYPES \
00045 typedef typename AllocatorBase<T>::value_type value_type;\
00046 typedef typename AllocatorBase<T>::size_type size_type;\
00047 typedef typename AllocatorBase<T>::difference_type difference_type;\
00048 typedef typename AllocatorBase<T>::pointer pointer;\
00049 typedef typename AllocatorBase<T>::const_pointer const_pointer;\
00050 typedef typename AllocatorBase<T>::reference reference;\
00051 typedef typename AllocatorBase<T>::const_reference const_reference;
00052
00053 #if defined(_MSC_VER) && (_MSC_VER < 1300)
00054
00055 #pragma warning(push)
00056 #pragma warning(disable: 4700) // VC60 workaround: don't know how to get rid of this warning
00057 #endif
00058
00059 template <class T, class A>
00060 typename A::pointer StandardReallocate(A& a, T *p, typename A::size_type oldSize, typename A::size_type newSize, bool preserve)
00061 {
00062 if (oldSize == newSize)
00063 return p;
00064
00065 if (preserve)
00066 {
00067 typename A::pointer newPointer = a.allocate(newSize, NULL);
00068 memcpy_s(newPointer, sizeof(T)*newSize, p, sizeof(T)*STDMIN(oldSize, newSize));
00069 a.deallocate(p, oldSize);
00070 return newPointer;
00071 }
00072 else
00073 {
00074 a.deallocate(p, oldSize);
00075 return a.allocate(newSize, NULL);
00076 }
00077 }
00078
00079 #if defined(_MSC_VER) && (_MSC_VER < 1300)
00080 #pragma warning(pop)
00081 #endif
00082
00083 template <class T, bool T_Align16 = false>
00084 class AllocatorWithCleanup : public AllocatorBase<T>
00085 {
00086 public:
00087 CRYPTOPP_INHERIT_ALLOCATOR_TYPES
00088
00089 pointer allocate(size_type n, const void * = NULL)
00090 {
00091 this->CheckSize(n);
00092 if (n == 0)
00093 return NULL;
00094
00095 #if CRYPTOPP_BOOL_ALIGN16_ENABLED
00096 if (T_Align16 && n*sizeof(T) >= 16)
00097 return (pointer)AlignedAllocate(n*sizeof(T));
00098 #endif
00099
00100 return (pointer)UnalignedAllocate(n*sizeof(T));
00101 }
00102
00103 void deallocate(void *p, size_type n)
00104 {
00105 SecureWipeArray((pointer)p, n);
00106
00107 #if CRYPTOPP_BOOL_ALIGN16_ENABLED
00108 if (T_Align16 && n*sizeof(T) >= 16)
00109 return AlignedDeallocate(p);
00110 #endif
00111
00112 UnalignedDeallocate(p);
00113 }
00114
00115 pointer reallocate(T *p, size_type oldSize, size_type newSize, bool preserve)
00116 {
00117 return StandardReallocate(*this, p, oldSize, newSize, preserve);
00118 }
00119
00120
00121
00122 template <class U> struct rebind { typedef AllocatorWithCleanup<U, T_Align16> other; };
00123 #if _MSC_VER >= 1500
00124 AllocatorWithCleanup() {}
00125 template <class U, bool A> AllocatorWithCleanup(const AllocatorWithCleanup<U, A> &) {}
00126 #endif
00127 };
00128
00129 CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup<byte>;
00130 CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup<word16>;
00131 CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup<word32>;
00132 CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup<word64>;
00133 #if CRYPTOPP_BOOL_X86
00134 CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup<word, true>;
00135 #endif
00136
00137 template <class T>
00138 class NullAllocator : public AllocatorBase<T>
00139 {
00140 public:
00141 CRYPTOPP_INHERIT_ALLOCATOR_TYPES
00142
00143 pointer allocate(size_type n, const void * = NULL)
00144 {
00145 assert(false);
00146 return NULL;
00147 }
00148
00149 void deallocate(void *p, size_type n)
00150 {
00151 assert(false);
00152 }
00153
00154 size_type max_size() const {return 0;}
00155 };
00156
00157
00158
00159
00160 template <class T, size_t S, class A = NullAllocator<T>, bool T_Align16 = false>
00161 class FixedSizeAllocatorWithCleanup : public AllocatorBase<T>
00162 {
00163 public:
00164 CRYPTOPP_INHERIT_ALLOCATOR_TYPES
00165
00166 FixedSizeAllocatorWithCleanup() : m_allocated(false) {}
00167
00168 pointer allocate(size_type n)
00169 {
00170 assert(IsAlignedOn(m_array, 8));
00171
00172 if (n <= S && !m_allocated)
00173 {
00174 m_allocated = true;
00175 return GetAlignedArray();
00176 }
00177 else
00178 return m_fallbackAllocator.allocate(n);
00179 }
00180
00181 pointer allocate(size_type n, const void *hint)
00182 {
00183 if (n <= S && !m_allocated)
00184 {
00185 m_allocated = true;
00186 return GetAlignedArray();
00187 }
00188 else
00189 return m_fallbackAllocator.allocate(n, hint);
00190 }
00191
00192 void deallocate(void *p, size_type n)
00193 {
00194 if (p == GetAlignedArray())
00195 {
00196 assert(n <= S);
00197 assert(m_allocated);
00198 m_allocated = false;
00199 SecureWipeArray((pointer)p, n);
00200 }
00201 else
00202 m_fallbackAllocator.deallocate(p, n);
00203 }
00204
00205 pointer reallocate(pointer p, size_type oldSize, size_type newSize, bool preserve)
00206 {
00207 if (p == GetAlignedArray() && newSize <= S)
00208 {
00209 assert(oldSize <= S);
00210 if (oldSize > newSize)
00211 SecureWipeArray(p+newSize, oldSize-newSize);
00212 return p;
00213 }
00214
00215 pointer newPointer = allocate(newSize, NULL);
00216 if (preserve)
00217 memcpy(newPointer, p, sizeof(T)*STDMIN(oldSize, newSize));
00218 deallocate(p, oldSize);
00219 return newPointer;
00220 }
00221
00222 size_type max_size() const {return STDMAX(m_fallbackAllocator.max_size(), S);}
00223
00224 private:
00225 #ifdef __BORLANDC__
00226 T* GetAlignedArray() {return m_array;}
00227 T m_array[S];
00228 #else
00229 T* GetAlignedArray() {return (CRYPTOPP_BOOL_ALIGN16_ENABLED && T_Align16) ? (T*)(((byte *)m_array) + (0-(size_t)m_array)%16) : m_array;}
00230 CRYPTOPP_ALIGN_DATA(8) T m_array[(CRYPTOPP_BOOL_ALIGN16_ENABLED && T_Align16) ? S+8/sizeof(T) : S];
00231 #endif
00232 A m_fallbackAllocator;
00233 bool m_allocated;
00234 };
00235
00236
00237 template <class T, class A = AllocatorWithCleanup<T> >
00238 class SecBlock
00239 {
00240 public:
00241 typedef typename A::value_type value_type;
00242 typedef typename A::pointer iterator;
00243 typedef typename A::const_pointer const_iterator;
00244 typedef typename A::size_type size_type;
00245
00246 explicit SecBlock(size_type size=0)
00247 : m_size(size) {m_ptr = m_alloc.allocate(size, NULL);}
00248 SecBlock(const SecBlock<T, A> &t)
00249 : m_size(t.m_size) {m_ptr = m_alloc.allocate(m_size, NULL); memcpy_s(m_ptr, m_size*sizeof(T), t.m_ptr, m_size*sizeof(T));}
00250 SecBlock(const T *t, size_type len)
00251 : m_size(len)
00252 {
00253 m_ptr = m_alloc.allocate(len, NULL);
00254 if (t == NULL)
00255 memset_z(m_ptr, 0, len*sizeof(T));
00256 else
00257 memcpy(m_ptr, t, len*sizeof(T));
00258 }
00259
00260 ~SecBlock()
00261 {m_alloc.deallocate(m_ptr, m_size);}
00262
00263 #ifdef __BORLANDC__
00264 operator T *() const
00265 {return (T*)m_ptr;}
00266 #else
00267 operator const void *() const
00268 {return m_ptr;}
00269 operator void *()
00270 {return m_ptr;}
00271
00272 operator const T *() const
00273 {return m_ptr;}
00274 operator T *()
00275 {return m_ptr;}
00276 #endif
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290 iterator begin()
00291 {return m_ptr;}
00292 const_iterator begin() const
00293 {return m_ptr;}
00294 iterator end()
00295 {return m_ptr+m_size;}
00296 const_iterator end() const
00297 {return m_ptr+m_size;}
00298
00299 typename A::pointer data() {return m_ptr;}
00300 typename A::const_pointer data() const {return m_ptr;}
00301
00302 size_type size() const {return m_size;}
00303 bool empty() const {return m_size == 0;}
00304
00305 byte * BytePtr() {return (byte *)m_ptr;}
00306 const byte * BytePtr() const {return (const byte *)m_ptr;}
00307 size_type SizeInBytes() const {return m_size*sizeof(T);}
00308
00309
00310 void Assign(const T *t, size_type len)
00311 {
00312 New(len);
00313 memcpy_s(m_ptr, m_size*sizeof(T), t, len*sizeof(T));
00314 }
00315
00316
00317 void Assign(const SecBlock<T, A> &t)
00318 {
00319 if (this != &t)
00320 {
00321 New(t.m_size);
00322 memcpy_s(m_ptr, m_size*sizeof(T), t.m_ptr, m_size*sizeof(T));
00323 }
00324 }
00325
00326 SecBlock<T, A>& operator=(const SecBlock<T, A> &t)
00327 {
00328 Assign(t);
00329 return *this;
00330 }
00331
00332
00333 SecBlock<T, A>& operator+=(const SecBlock<T, A> &t)
00334 {
00335 size_type oldSize = m_size;
00336 Grow(m_size+t.m_size);
00337 memcpy_s(m_ptr+oldSize, m_size*sizeof(T), t.m_ptr, t.m_size*sizeof(T));
00338 return *this;
00339 }
00340
00341
00342 SecBlock<T, A> operator+(const SecBlock<T, A> &t)
00343 {
00344 SecBlock<T, A> result(m_size+t.m_size);
00345 memcpy_s(result.m_ptr, result.m_size*sizeof(T), m_ptr, m_size*sizeof(T));
00346 memcpy_s(result.m_ptr+m_size, t.m_size*sizeof(T), t.m_ptr, t.m_size*sizeof(T));
00347 return result;
00348 }
00349
00350 bool operator==(const SecBlock<T, A> &t) const
00351 {
00352 return m_size == t.m_size && VerifyBufsEqual(m_ptr, t.m_ptr, m_size*sizeof(T));
00353 }
00354
00355 bool operator!=(const SecBlock<T, A> &t) const
00356 {
00357 return !operator==(t);
00358 }
00359
00360
00361 void New(size_type newSize)
00362 {
00363 m_ptr = m_alloc.reallocate(m_ptr, m_size, newSize, false);
00364 m_size = newSize;
00365 }
00366
00367
00368 void CleanNew(size_type newSize)
00369 {
00370 New(newSize);
00371 memset_z(m_ptr, 0, m_size*sizeof(T));
00372 }
00373
00374
00375 void Grow(size_type newSize)
00376 {
00377 if (newSize > m_size)
00378 {
00379 m_ptr = m_alloc.reallocate(m_ptr, m_size, newSize, true);
00380 m_size = newSize;
00381 }
00382 }
00383
00384
00385 void CleanGrow(size_type newSize)
00386 {
00387 if (newSize > m_size)
00388 {
00389 m_ptr = m_alloc.reallocate(m_ptr, m_size, newSize, true);
00390 memset(m_ptr+m_size, 0, (newSize-m_size)*sizeof(T));
00391 m_size = newSize;
00392 }
00393 }
00394
00395
00396 void resize(size_type newSize)
00397 {
00398 m_ptr = m_alloc.reallocate(m_ptr, m_size, newSize, true);
00399 m_size = newSize;
00400 }
00401
00402
00403 void swap(SecBlock<T, A> &b)
00404 {
00405 std::swap(m_alloc, b.m_alloc);
00406 std::swap(m_size, b.m_size);
00407 std::swap(m_ptr, b.m_ptr);
00408 }
00409
00410
00411 A m_alloc;
00412 size_type m_size;
00413 T *m_ptr;
00414 };
00415
00416 typedef SecBlock<byte> SecByteBlock;
00417 typedef SecBlock<byte, AllocatorWithCleanup<byte, true> > AlignedSecByteBlock;
00418 typedef SecBlock<word> SecWordBlock;
00419
00420
00421 template <class T, unsigned int S, class A = FixedSizeAllocatorWithCleanup<T, S> >
00422 class FixedSizeSecBlock : public SecBlock<T, A>
00423 {
00424 public:
00425 explicit FixedSizeSecBlock() : SecBlock<T, A>(S) {}
00426 };
00427
00428 template <class T, unsigned int S, bool T_Align16 = true>
00429 class FixedSizeAlignedSecBlock : public FixedSizeSecBlock<T, S, FixedSizeAllocatorWithCleanup<T, S, NullAllocator<T>, T_Align16> >
00430 {
00431 };
00432
00433
00434 template <class T, unsigned int S, class A = FixedSizeAllocatorWithCleanup<T, S, AllocatorWithCleanup<T> > >
00435 class SecBlockWithHint : public SecBlock<T, A>
00436 {
00437 public:
00438 explicit SecBlockWithHint(size_t size) : SecBlock<T, A>(size) {}
00439 };
00440
00441 template<class T, bool A, class U, bool B>
00442 inline bool operator==(const CryptoPP::AllocatorWithCleanup<T, A>&, const CryptoPP::AllocatorWithCleanup<U, B>&) {return (true);}
00443 template<class T, bool A, class U, bool B>
00444 inline bool operator!=(const CryptoPP::AllocatorWithCleanup<T, A>&, const CryptoPP::AllocatorWithCleanup<U, B>&) {return (false);}
00445
00446 NAMESPACE_END
00447
00448 NAMESPACE_BEGIN(std)
00449 template <class T, class A>
00450 inline void swap(CryptoPP::SecBlock<T, A> &a, CryptoPP::SecBlock<T, A> &b)
00451 {
00452 a.swap(b);
00453 }
00454
00455 #if defined(_STLP_DONT_SUPPORT_REBIND_MEMBER_TEMPLATE) || (defined(_STLPORT_VERSION) && !defined(_STLP_MEMBER_TEMPLATE_CLASSES))
00456
00457 template <class _Tp1, class _Tp2>
00458 inline CryptoPP::AllocatorWithCleanup<_Tp2>&
00459 __stl_alloc_rebind(CryptoPP::AllocatorWithCleanup<_Tp1>& __a, const _Tp2*)
00460 {
00461 return (CryptoPP::AllocatorWithCleanup<_Tp2>&)(__a);
00462 }
00463 #endif
00464
00465 NAMESPACE_END
00466
00467 #endif