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