- 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 <string.h>             // CodeWarrior doesn't have memory.h
    00009 #include <assert.h>
    00010
    00011 NAMESPACE_BEGIN(CryptoPP)
    00012
    00013 // ************** secure memory allocation ***************
    00014
    00015 template<class T>
    00016 class AllocatorBase
    00017 {
    00018 public:
    00019         typedef T value_type;
    00020         typedef size_t size_type;
    00021 #ifdef CRYPTOPP_MSVCRT6
    00022         typedef ptrdiff_t difference_type;
    00023 #else
    00024         typedef std::ptrdiff_t difference_type;
    00025 #endif
    00026         typedef T * pointer;
    00027         typedef const T * const_pointer;
    00028         typedef T & reference;
    00029         typedef const T & const_reference;
    00030
    00031         pointer address(reference r) const {return (&r);}
    00032         const_pointer address(const_reference r) const {return (&r); }
    00033         void construct(pointer p, const T& val) {new (p) T(val);}
    00034         void destroy(pointer p) {p->~T();}
    00035         size_type max_size() const {return ~size_type(0)/sizeof(T);}    // switch to std::numeric_limits<T>::max later
    00036
    00037 protected:
    00038         static void CheckSize(size_t n)
    00039         {
    00040                 if (n > ~size_t(0) / sizeof(T))
    00041                         throw InvalidArgument("AllocatorBase: requested size would cause integer overflow");
    00042         }
    00043 };
    00044
    00045 #define CRYPTOPP_INHERIT_ALLOCATOR_TYPES        \
    00046 typedef typename AllocatorBase<T>::value_type value_type;\
    00047 typedef typename AllocatorBase<T>::size_type size_type;\
    00048 typedef typename AllocatorBase<T>::difference_type difference_type;\
    00049 typedef typename AllocatorBase<T>::pointer pointer;\
    00050 typedef typename AllocatorBase<T>::const_pointer const_pointer;\
    00051 typedef typename AllocatorBase<T>::reference reference;\
    00052 typedef typename AllocatorBase<T>::const_reference const_reference;
    00053
    00054 #if defined(_MSC_VER) && (_MSC_VER < 1300)
    00055 // this pragma causes an internal compiler error if placed immediately before std::swap(a, b)
    00056 #pragma warning(push)
    00057 #pragma warning(disable: 4700)  // VC60 workaround: don't know how to get rid of this warning
    00058 #endif
    00059
    00060 template <class T, class A>
    00061 typename A::pointer StandardReallocate(A& a, T *p, typename A::size_type oldSize, typename A::size_type newSize, bool preserve)
    00062 {
    00063         if (oldSize == newSize)
    00064                 return p;
    00065
    00066         if (preserve)
    00067         {
    00068                 A b;
    00069                 typename A::pointer newPointer = b.allocate(newSize, NULL);
    00070                 memcpy_s(newPointer, sizeof(T)*newSize, p, sizeof(T)*STDMIN(oldSize, newSize));
    00071                 a.deallocate(p, oldSize);
    00072                 std::swap(a, b);
    00073                 return newPointer;
    00074         }
    00075         else
    00076         {
    00077                 a.deallocate(p, oldSize);
    00078                 return a.allocate(newSize, NULL);
    00079         }
    00080 }
    00081
    00082 #if defined(_MSC_VER) && (_MSC_VER < 1300)
    00083 #pragma warning(pop)
    00084 #endif
    00085
    00086 template <class T>
    00087 class AllocatorWithCleanup : public AllocatorBase<T>
    00088 {
    00089 public:
    00090         CRYPTOPP_INHERIT_ALLOCATOR_TYPES
    00091
    00092         pointer allocate(size_type n, const void * = NULL)
    00093         {
    00094                 CheckSize(n);
    00095                 if (n == 0)
    00096                         return NULL;
    00097                 return new T[n];
    00098         }
    00099
    00100         void deallocate(void *p, size_type n)
    00101         {
    00102                 memset(p, 0, n*sizeof(T));
    00103                 delete [] (T *)p;
    00104         }
    00105
    00106         pointer reallocate(T *p, size_type oldSize, size_type newSize, bool preserve)
    00107         {
    00108                 return StandardReallocate(*this, p, oldSize, newSize, preserve);
    00109         }
    00110
    00111         // VS.NET STL enforces the policy of "All STL-compliant allocators have to provide a
    00112         // template class member called rebind".
    00113     template <class U> struct rebind { typedef AllocatorWithCleanup<U> other; };
    00114 };
    00115
    00116 CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup<byte>;
    00117 CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup<word16>;
    00118 CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup<word32>;
    00119
    00120 template <class T>
    00121 class NullAllocator : public AllocatorBase<T>
    00122 {
    00123 public:
    00124         CRYPTOPP_INHERIT_ALLOCATOR_TYPES
    00125
    00126         pointer allocate(size_type n, const void * = NULL)
    00127         {
    00128                 assert(false);
    00129                 return NULL;
    00130         }
    00131
    00132         void deallocate(void *p, size_type n)
    00133         {
    00134                 assert(false);
    00135         }
    00136
    00137         size_type max_size() const {return 0;}
    00138 };
    00139
    00140 // This allocator can't be used with standard collections because
    00141 // they require that all objects of the same allocator type are equivalent.
    00142 // So this is for use with SecBlock only.
    00143 template <class T, size_t S, class A = NullAllocator<T> >
    00144 class FixedSizeAllocatorWithCleanup : public AllocatorBase<T>
    00145 {
    00146 public:
    00147         CRYPTOPP_INHERIT_ALLOCATOR_TYPES
    00148
    00149         FixedSizeAllocatorWithCleanup() : m_allocated(false) {}
    00150
    00151         pointer allocate(size_type n)
    00152         {
    00153                 if (n <= S && !m_allocated)
    00154                 {
    00155                         m_allocated = true;
    00156                         return m_array;
    00157                 }
    00158                 else
    00159                         return m_fallbackAllocator.allocate(n);
    00160         }
    00161
    00162         pointer allocate(size_type n, const void *hint)
    00163         {
    00164                 if (n <= S && !m_allocated)
    00165                 {
    00166                         m_allocated = true;
    00167                         return m_array;
    00168                 }
    00169                 else
    00170                         return m_fallbackAllocator.allocate(n, hint);
    00171         }
    00172
    00173         void deallocate(void *p, size_type n)
    00174         {
    00175                 if (p == m_array)
    00176                 {
    00177                         assert(n <= S);
    00178                         assert(m_allocated);
    00179                         m_allocated = false;
    00180                         memset(p, 0, n*sizeof(T));
    00181                 }
    00182                 else
    00183                         m_fallbackAllocator.deallocate(p, n);
    00184         }
    00185
    00186         pointer reallocate(pointer p, size_type oldSize, size_type newSize, bool preserve)
    00187         {
    00188                 if (p == m_array && newSize <= S)
    00189                 {
    00190                         assert(oldSize <= S);
    00191                         if (oldSize > newSize)
    00192                                 memset(p + newSize, 0, (oldSize-newSize)*sizeof(T));
    00193                         return p;
    00194                 }
    00195
    00196                 pointer newPointer = allocate(newSize, NULL);
    00197                 if (preserve)
    00198                         memcpy(newPointer, p, sizeof(T)*STDMIN(oldSize, newSize));
    00199                 deallocate(p, oldSize);
    00200                 return newPointer;
    00201         }
    00202
    00203         size_type max_size() const {return STDMAX(m_fallbackAllocator.max_size(), S);}
    00204
    00205 private:
    00206         T m_array[S];
    00207         A m_fallbackAllocator;
    00208         bool m_allocated;
    00209 };
    00210
    00211 //! a block of memory allocated using A
    00212 template <class T, class A = AllocatorWithCleanup<T> >
    00213 class SecBlock
    00214 {
    00215 public:
    00216         typedef typename A::value_type value_type;
    00217         typedef typename A::pointer iterator;
    00218         typedef typename A::const_pointer const_iterator;
    00219         typedef typename A::size_type size_type;
    00220
    00221     explicit SecBlock(size_type size=0)
    00222                 : m_size(size) {m_ptr = m_alloc.allocate(size, NULL);}
    00223         SecBlock(const SecBlock<T, A> &t)
    00224                 : 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));}
    00225         SecBlock(const T *t, size_type len)
    00226                 : m_size(len)
    00227         {
    00228                 m_ptr = m_alloc.allocate(len, NULL);
    00229                 if (t == NULL)
    00230                         memset(m_ptr, 0, len*sizeof(T));
    00231                 else
    00232                         memcpy(m_ptr, t, len*sizeof(T));
    00233         }
    00234
    00235         ~SecBlock()
    00236                 {m_alloc.deallocate(m_ptr, m_size);}
    00237
    00238 #ifndef __BORLANDC__
    00239         operator const void *() const
    00240                 {return m_ptr;}
    00241         operator void *()
    00242                 {return m_ptr;}
    00243
    00244         operator const T *() const
    00245                 {return m_ptr;}
    00246 #endif
    00247         operator T *()
    00248                 {return m_ptr;}
    00249
    00250 //      T *operator +(size_type offset)
    00251 //              {return m_ptr+offset;}
    00252
    00253 //      const T *operator +(size_type offset) const
    00254 //              {return m_ptr+offset;}
    00255
    00256 //      T& operator[](size_type index)
    00257 //              {assert(index >= 0 && index < m_size); return m_ptr[index];}
    00258
    00259 //      const T& operator[](size_type index) const
    00260 //              {assert(index >= 0 && index < m_size); return m_ptr[index];}
    00261
    00262         iterator begin()
    00263                 {return m_ptr;}
    00264         const_iterator begin() const
    00265                 {return m_ptr;}
    00266         iterator end()
    00267                 {return m_ptr+m_size;}
    00268         const_iterator end() const
    00269                 {return m_ptr+m_size;}
    00270
    00271         typename A::pointer data() {return m_ptr;}
    00272         typename A::const_pointer data() const {return m_ptr;}
    00273
    00274         size_type size() const {return m_size;}
    00275         bool empty() const {return m_size == 0;}
    00276
    00277         size_type SizeInBytes() const {return m_size*sizeof(T);}
    00278
    00279         void Assign(const T *t, size_type len)
    00280         {
    00281                 New(len);
    00282                 memcpy_s(m_ptr, m_size*sizeof(T), t, len*sizeof(T));
    00283         }
    00284
    00285         void Assign(const SecBlock<T, A> &t)
    00286         {
    00287                 New(t.m_size);
    00288                 memcpy_s(m_ptr, m_size*sizeof(T), t.m_ptr, m_size*sizeof(T));
    00289         }
    00290
    00291         SecBlock<T, A>& operator=(const SecBlock<T, A> &t)
    00292         {
    00293                 Assign(t);
    00294                 return *this;
    00295         }
    00296
    00297         SecBlock<T, A>& operator+=(const SecBlock<T, A> &t)
    00298         {
    00299                 size_type oldSize = m_size;
    00300                 Grow(m_size+t.m_size);
    00301                 memcpy_s(m_ptr+oldSize, m_size*sizeof(T), t.m_ptr, t.m_size*sizeof(T));
    00302                 return *this;
    00303         }
    00304
    00305         SecBlock<T, A> operator+(const SecBlock<T, A> &t)
    00306         {
    00307                 SecBlock<T, A> result(m_size+t.m_size);
    00308                 memcpy_s(result.m_ptr, result.m_size*sizeof(T), m_ptr, m_size*sizeof(T));
    00309                 memcpy_s(result.m_ptr+m_size, t.m_size*sizeof(T), t.m_ptr, t.m_size*sizeof(T));
    00310                 return result;
    00311         }
    00312
    00313         bool operator==(const SecBlock<T, A> &t) const
    00314         {
    00315                 return m_size == t.m_size && memcmp(m_ptr, t.m_ptr, m_size*sizeof(T)) == 0;
    00316         }
    00317
    00318         bool operator!=(const SecBlock<T, A> &t) const
    00319         {
    00320                 return !operator==(t);
    00321         }
    00322
    00323         void New(size_type newSize)
    00324         {
    00325                 m_ptr = m_alloc.reallocate(m_ptr, m_size, newSize, false);
    00326                 m_size = newSize;
    00327         }
    00328
    00329         void CleanNew(size_type newSize)
    00330         {
    00331                 New(newSize);
    00332                 memset(m_ptr, 0, m_size*sizeof(T));
    00333         }
    00334
    00335         void Grow(size_type newSize)
    00336         {
    00337                 if (newSize > m_size)
    00338                 {
    00339                         m_ptr = m_alloc.reallocate(m_ptr, m_size, newSize, true);
    00340                         m_size = newSize;
    00341                 }
    00342         }
    00343
    00344         void CleanGrow(size_type newSize)
    00345         {
    00346                 if (newSize > m_size)
    00347                 {
    00348                         m_ptr = m_alloc.reallocate(m_ptr, m_size, newSize, true);
    00349                         memset(m_ptr+m_size, 0, (newSize-m_size)*sizeof(T));
    00350                         m_size = newSize;
    00351                 }
    00352         }
    00353
    00354         void resize(size_type newSize)
    00355         {
    00356                 m_ptr = m_alloc.reallocate(m_ptr, m_size, newSize, true);
    00357                 m_size = newSize;
    00358         }
    00359
    00360         void swap(SecBlock<T, A> &b)
    00361         {
    00362                 std::swap(m_alloc, b.m_alloc);
    00363                 std::swap(m_size, b.m_size);
    00364                 std::swap(m_ptr, b.m_ptr);
    00365         }
    00366
    00367 //private:
    00368         A m_alloc;
    00369         size_type m_size;
    00370         T *m_ptr;
    00371 };
    00372
    00373 typedef SecBlock<byte> SecByteBlock;
    00374 typedef SecBlock<word> SecWordBlock;
    00375
    00376 template <class T, unsigned int S, class A = FixedSizeAllocatorWithCleanup<T, S> >
    00377 class FixedSizeSecBlock : public SecBlock<T, A>
    00378 {
    00379 public:
    00380         explicit FixedSizeSecBlock() : SecBlock<T, A>(S) {}
    00381 };
    00382
    00383 template <class T, unsigned int S, class A = FixedSizeAllocatorWithCleanup<T, S, AllocatorWithCleanup<T> > >
    00384 class SecBlockWithHint : public SecBlock<T, A>
    00385 {
    00386 public:
    00387         explicit SecBlockWithHint(size_t size) : SecBlock<T, A>(size) {}
    00388 };
    00389
    00390 template<class T, class U>
    00391 inline bool operator==(const CryptoPP::AllocatorWithCleanup<T>&, const CryptoPP::AllocatorWithCleanup<U>&) {return (true);}
    00392 template<class T, class U>
    00393 inline bool operator!=(const CryptoPP::AllocatorWithCleanup<T>&, const CryptoPP::AllocatorWithCleanup<U>&) {return (false);}
    00394
    00395 NAMESPACE_END
    00396
    00397 NAMESPACE_BEGIN(std)
    00398 template <class T, class A>
    00399 inline void swap(CryptoPP::SecBlock<T, A> &a, CryptoPP::SecBlock<T, A> &b)
    00400 {
    00401         a.swap(b);
    00402 }
    00403
    00404 #if defined(_STLPORT_VERSION) && !defined(_STLP_MEMBER_TEMPLATE_CLASSES)
    00405 template <class _Tp1, class _Tp2>
    00406 inline CryptoPP::AllocatorWithCleanup<_Tp2>&
    00407 __stl_alloc_rebind(CryptoPP::AllocatorWithCleanup<_Tp1>& __a, const _Tp2*)
    00408 {
    00409         return (CryptoPP::AllocatorWithCleanup<_Tp2>&)(__a);
    00410 }
    00411 #endif
    00412
    00413 NAMESPACE_END
    00414
    00415 #endif