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

Generated on Tue Jul 8 23:34:24 2003 for Crypto++ by doxygen 1.3.2