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