• Main Page
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

secblock.h

00001 // secblock.h - written and placed in the public domain by Wei Dai
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 // ************** secure memory allocation ***************
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);}    // switch to std::numeric_limits<T>::max later
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 // this pragma causes an internal compiler error if placed immediately before std::swap(a, b)
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                 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         // VS.NET STL enforces the policy of "All STL-compliant allocators have to provide a
00121         // template class member called rebind".
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>;   // for Integer
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 // This allocator can't be used with standard collections because
00158 // they require that all objects of the same allocator type are equivalent.
00159 // So this is for use with SecBlock only.
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 //! a block of memory allocated using A
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 //      T *operator +(size_type offset)
00279 //              {return m_ptr+offset;}
00280 
00281 //      const T *operator +(size_type offset) const
00282 //              {return m_ptr+offset;}
00283 
00284 //      T& operator[](size_type index)
00285 //              {assert(index >= 0 && index < m_size); return m_ptr[index];}
00286 
00287 //      const T& operator[](size_type index) const
00288 //              {assert(index >= 0 && index < m_size); return m_ptr[index];}
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         //! set contents and size
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         //! copy contents and size from another SecBlock
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         // append to this object
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         // append operator
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         //! change size, without preserving contents
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         //! change size and set contents to 0
00368         void CleanNew(size_type newSize)
00369         {
00370                 New(newSize);
00371                 memset_z(m_ptr, 0, m_size*sizeof(T));
00372         }
00373 
00374         //! change size only if newSize > current size. contents are preserved
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         //! change size only if newSize > current size. contents are preserved and additional area is set to 0
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         //! change size and preserve contents
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         //! swap contents and size with another SecBlock
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 //private:
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 //! a SecBlock with fixed size, allocated statically
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 //! a SecBlock that preallocates size S statically, and uses the heap when this size is exceeded
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 // working for STLport 5.1.3 and MSVC 6 SP5
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

Generated on Mon Aug 9 2010 15:56:36 for Crypto++ by  doxygen 1.7.1