Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | 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 template <class T, class A>
    00055 typename A::pointer StandardReallocate(A& a, T *p, typename A::size_type oldSize, typename A::size_type newSize, bool preserve)
    00056 {
    00057         if (oldSize == newSize)
    00058                 return p;
    00059
    00060         if (preserve)
    00061         {
    00062                 A b;
    00063                 typename A::pointer newPointer = b.allocate(newSize, NULL);
    00064                 memcpy(newPointer, p, sizeof(T)*STDMIN(oldSize, newSize));
    00065                 a.deallocate(p, oldSize);
    00066                 std::swap(a, b);
    00067                 return newPointer;
    00068         }
    00069         else
    00070         {
    00071                 a.deallocate(p, oldSize);
    00072                 return a.allocate(newSize, NULL);
    00073         }
    00074 }
    00075
    00076 template <class T>
    00077 class AllocatorWithCleanup : public AllocatorBase<T>
    00078 {
    00079 public:
    00080         CRYPTOPP_INHERIT_ALLOCATOR_TYPES
    00081
    00082         pointer allocate(size_type n, const void * = NULL)
    00083         {
    00084                 CheckSize(n);
    00085                 if (n == 0)
    00086                         return NULL;
    00087                 return new T[n];
    00088         }
    00089
    00090         void deallocate(void *p, size_type n)
    00091         {
    00092                 memset(p, 0, n*sizeof(T));
    00093                 delete [] (T *)p;
    00094         }
    00095
    00096         pointer reallocate(T *p, size_type oldSize, size_type newSize, bool preserve)
    00097         {
    00098                 return StandardReallocate(*this, p, oldSize, newSize, preserve);
    00099         }
    00100
    00101         // VS.NET STL enforces the policy of "All STL-compliant allocators have to provide a
    00102         // template class member called rebind".
    00103     template <class U> struct rebind { typedef AllocatorWithCleanup<U> other; };
    00104 };
    00105
    00106 CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup<byte>;
    00107 CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup<word16>;
    00108 CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup<word32>;
    00109
    00110 template <class T>
    00111 class NullAllocator : public AllocatorBase<T>
    00112 {
    00113 public:
    00114         CRYPTOPP_INHERIT_ALLOCATOR_TYPES
    00115
    00116         pointer allocate(size_type n, const void * = NULL)
    00117         {
    00118                 assert(false);
    00119                 return NULL;
    00120         }
    00121
    00122         void deallocate(void *p, size_type n)
    00123         {
    00124                 assert(false);
    00125         }
    00126
    00127         size_type max_size() const {return 0;}
    00128 };
    00129
    00130 // This allocator can't be used with standard collections because
    00131 // they require that all objects of the same allocator type are equivalent.
    00132 // So this is for use with SecBlock only.
    00133 template <class T, size_t S, class A = NullAllocator<T> >
    00134 class FixedSizeAllocatorWithCleanup : public AllocatorBase<T>
    00135 {
    00136 public:
    00137         CRYPTOPP_INHERIT_ALLOCATOR_TYPES
    00138
    00139         FixedSizeAllocatorWithCleanup() : m_allocated(false) {}
    00140
    00141         pointer allocate(size_type n)
    00142         {
    00143                 if (n <= S && !m_allocated)
    00144                 {
    00145                         m_allocated = true;
    00146                         return m_array;
    00147                 }
    00148                 else
    00149                         return m_fallbackAllocator.allocate(n);
    00150         }
    00151
    00152         pointer allocate(size_type n, const void *hint)
    00153         {
    00154                 if (n <= S && !m_allocated)
    00155                 {
    00156                         m_allocated = true;
    00157                         return m_array;
    00158                 }
    00159                 else
    00160                         return m_fallbackAllocator.allocate(n, hint);
    00161         }
    00162
    00163         void deallocate(void *p, size_type n)
    00164         {
    00165                 if (p == m_array)
    00166                 {
    00167                         assert(n <= S);
    00168                         assert(m_allocated);
    00169                         m_allocated = false;
    00170                         memset(p, 0, n*sizeof(T));
    00171                 }
    00172                 else
    00173                         m_fallbackAllocator.deallocate(p, n);
    00174         }
    00175
    00176         pointer reallocate(pointer p, size_type oldSize, size_type newSize, bool preserve)
    00177         {
    00178                 if (p == m_array && newSize <= S)
    00179                 {
    00180                         assert(oldSize <= S);
    00181                         if (oldSize > newSize)
    00182                                 memset(p + newSize, 0, (oldSize-newSize)*sizeof(T));
    00183                         return p;
    00184                 }
    00185
    00186                 pointer newPointer = allocate(newSize, NULL);
    00187                 if (preserve)
    00188                         memcpy(newPointer, p, sizeof(T)*STDMIN(oldSize, newSize));
    00189                 deallocate(p, oldSize);
    00190                 return newPointer;
    00191         }
    00192
    00193         size_type max_size() const {return STDMAX(m_fallbackAllocator.max_size(), S);}
    00194
    00195 private:
    00196         T m_array[S];
    00197         A m_fallbackAllocator;
    00198         bool m_allocated;
    00199 };
    00200
    00201 //! a block of memory allocated using A
    00202 template <class T, class A = AllocatorWithCleanup<T> >
    00203 class SecBlock
    00204 {
    00205 public:
    00206     explicit SecBlock(unsigned int size=0)
    00207                 : m_size(size) {m_ptr = m_alloc.allocate(size, NULL);}
    00208         SecBlock(const SecBlock<T, A> &t)
    00209                 : m_size(t.m_size) {m_ptr = m_alloc.allocate(m_size, NULL); memcpy(m_ptr, t.m_ptr, m_size*sizeof(T));}
    00210         SecBlock(const T *t, unsigned int len)
    00211                 : m_size(len)
    00212         {
    00213                 m_ptr = m_alloc.allocate(len, NULL);
    00214                 if (t == NULL)
    00215                         memset(m_ptr, 0, len*sizeof(T));
    00216                 else
    00217                         memcpy(m_ptr, t, len*sizeof(T));
    00218         }
    00219
    00220         ~SecBlock()
    00221                 {m_alloc.deallocate(m_ptr, m_size);}
    00222
    00223         operator const void *() const
    00224                 {return m_ptr;}
    00225         operator void *()
    00226                 {return m_ptr;}
    00227 #if defined(__GNUC__) && __GNUC__ < 3   // reduce warnings
    00228         operator const void *()
    00229                 {return m_ptr;}
    00230 #endif
    00231
    00232         operator const T *() const
    00233                 {return m_ptr;}
    00234         operator T *()
    00235                 {return m_ptr;}
    00236 #if defined(__GNUC__) && __GNUC__ < 3   // reduce warnings
    00237         operator const T *()
    00238                 {return m_ptr;}
    00239 #endif
    00240
    00241         template <typename I>
    00242         T *operator +(I offset)
    00243                 {return m_ptr+offset;}
    00244
    00245         template <typename I>
    00246         const T *operator +(I offset) const
    00247                 {return m_ptr+offset;}
    00248
    00249         template <typename I>
    00250         T& operator[](I index)
    00251                 {assert(index >= 0 && (unsigned int)index < m_size); return m_ptr[index];}
    00252
    00253         template <typename I>
    00254         const T& operator[](I index) const
    00255                 {assert(index >= 0 && (unsigned int)index < m_size); return m_ptr[index];}
    00256
    00257         typedef typename A::value_type value_type;
    00258         typedef typename A::pointer iterator;
    00259         typedef typename A::const_pointer const_iterator;
    00260         typedef typename A::size_type size_type;
    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         void Assign(const T *t, unsigned int len)
    00278         {
    00279                 New(len);
    00280                 memcpy(m_ptr, t, len*sizeof(T));
    00281         }
    00282
    00283         void Assign(const SecBlock<T, A> &t)
    00284         {
    00285                 New(t.m_size);
    00286                 memcpy(m_ptr, t.m_ptr, m_size*sizeof(T));
    00287         }
    00288
    00289         SecBlock& operator=(const SecBlock<T, A> &t)
    00290         {
    00291                 Assign(t);
    00292                 return *this;
    00293         }
    00294
    00295         bool operator==(const SecBlock<T, A> &t) const
    00296         {
    00297                 return m_size == t.m_size && memcmp(m_ptr, t.m_ptr, m_size*sizeof(T)) == 0;
    00298         }
    00299
    00300         bool operator!=(const SecBlock<T, A> &t) const
    00301         {
    00302                 return !operator==(t);
    00303         }
    00304
    00305         void New(unsigned int newSize)
    00306         {
    00307                 m_ptr = m_alloc.reallocate(m_ptr, m_size, newSize, false);
    00308                 m_size = newSize;
    00309         }
    00310
    00311         void CleanNew(unsigned int newSize)
    00312         {
    00313                 New(newSize);
    00314                 memset(m_ptr, 0, m_size*sizeof(T));
    00315         }
    00316
    00317         void Grow(unsigned int newSize)
    00318         {
    00319                 if (newSize > m_size)
    00320                 {
    00321                         m_ptr = m_alloc.reallocate(m_ptr, m_size, newSize, true);
    00322                         m_size = newSize;
    00323                 }
    00324         }
    00325
    00326         void CleanGrow(unsigned int newSize)
    00327         {
    00328                 if (newSize > m_size)
    00329                 {
    00330                         m_ptr = m_alloc.reallocate(m_ptr, m_size, newSize, true);
    00331                         memset(m_ptr+m_size, 0, (newSize-m_size)*sizeof(T));
    00332                         m_size = newSize;
    00333                 }
    00334         }
    00335
    00336         void resize(unsigned int newSize)
    00337         {
    00338                 m_ptr = m_alloc.reallocate(m_ptr, m_size, newSize, true);
    00339                 m_size = newSize;
    00340         }
    00341
    00342         void swap(SecBlock<T, A> &b)
    00343         {
    00344                 std::swap(m_alloc, b.m_alloc);
    00345                 std::swap(m_size, b.m_size);
    00346                 std::swap(m_ptr, b.m_ptr);
    00347         }
    00348
    00349 //private:
    00350         A m_alloc;
    00351         unsigned int m_size;
    00352         T *m_ptr;
    00353 };
    00354
    00355 typedef SecBlock<byte> SecByteBlock;
    00356 typedef SecBlock<word> SecWordBlock;
    00357
    00358 template <class T, unsigned int S, class A = FixedSizeAllocatorWithCleanup<T, S> >
    00359 class FixedSizeSecBlock : public SecBlock<T, A>
    00360 {
    00361 public:
    00362         explicit FixedSizeSecBlock() : SecBlock<T, A>(S) {}
    00363 };
    00364
    00365 template <class T, unsigned int S, class A = FixedSizeAllocatorWithCleanup<T, S, AllocatorWithCleanup<T> > >
    00366 class SecBlockWithHint : public SecBlock<T, A>
    00367 {
    00368 public:
    00369         explicit SecBlockWithHint(unsigned int size) : SecBlock<T, A>(size) {}
    00370 };
    00371
    00372 template<class T, class U>
    00373 inline bool operator==(const CryptoPP::AllocatorWithCleanup<T>&, const CryptoPP::AllocatorWithCleanup<U>&) {return (true);}
    00374 template<class T, class U>
    00375 inline bool operator!=(const CryptoPP::AllocatorWithCleanup<T>&, const CryptoPP::AllocatorWithCleanup<U>&) {return (false);}
    00376
    00377 NAMESPACE_END
    00378
    00379 NAMESPACE_BEGIN(std)
    00380 template <class T, class A>
    00381 inline void swap(CryptoPP::SecBlock<T, A> &a, CryptoPP::SecBlock<T, A> &b)
    00382 {
    00383         a.swap(b);
    00384 }
    00385
    00386 #if defined(_STLPORT_VERSION) && !defined(_STLP_MEMBER_TEMPLATE_CLASSES)
    00387 template <class _Tp1, class _Tp2>
    00388 inline CryptoPP::AllocatorWithCleanup<_Tp2>&
    00389 __stl_alloc_rebind(CryptoPP::AllocatorWithCleanup<_Tp1>& __a, const _Tp2*)
    00390 {
    00391         return (CryptoPP::AllocatorWithCleanup<_Tp2>&)(__a);
    00392 }
    00393 #endif
    00394
    00395 NAMESPACE_END
    00396
    00397 #endif