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