Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | 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 "cryptopp_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 #if (defined(_MSC_VER) && _MSC_VER < 1300)
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 template <class T>
00098 class NullAllocator : public AllocatorBase<T>
00099 {
00100 public:
00101         CRYPTOPP_INHERIT_ALLOCATOR_TYPES
00102 
00103         pointer allocate(size_type n, const void * = NULL)
00104         {
00105                 assert(false);
00106                 return NULL;
00107         }
00108 
00109         void deallocate(void *p, size_type n)
00110         {
00111                 assert(false);
00112         }
00113 };
00114 
00115 // this allocator can't be used with standard collections
00116 template <class T, unsigned int S, class A = NullAllocator<T> >
00117 class FixedSizeAllocatorWithCleanup : public AllocatorBase<T>
00118 {
00119 public:
00120         CRYPTOPP_INHERIT_ALLOCATOR_TYPES
00121 
00122         pointer allocate(size_type n)
00123         {
00124                 if (n <= S)
00125                 {
00126                         assert(!m_allocated);
00127 #ifndef NDEBUG
00128                         m_allocated = true;
00129 #endif
00130                         return m_array;
00131                 }
00132                 else
00133                         return m_fallbackAllocator.allocate(n);
00134         }
00135 
00136         pointer allocate(size_type n, const void *hint)
00137         {
00138                 if (n <= S)
00139                 {
00140                         assert(!m_allocated);
00141 #ifndef NDEBUG
00142                         m_allocated = true;
00143 #endif
00144                         return m_array;
00145                 }
00146                 else
00147                         return m_fallbackAllocator.allocate(n, hint);
00148         }
00149 
00150         void deallocate(void *p, size_type n)
00151         {
00152                 if (n <= S)
00153                 {
00154                         assert(m_allocated);
00155                         assert(p == m_array);
00156 #ifndef NDEBUG
00157                         m_allocated = false;
00158 #endif
00159                         memset(p, 0, n*sizeof(T));
00160                 }
00161                 else
00162                         m_fallbackAllocator.deallocate(p, n);
00163         }
00164 
00165         pointer reallocate(pointer p, size_type oldSize, size_type newSize, bool preserve)
00166         {
00167                 if (oldSize <= S && newSize <= S)
00168                         return p;
00169 
00170                 return StandardReallocate(*this, p, oldSize, newSize, preserve);
00171         }
00172 
00173         size_type max_size() const {return m_fallbackAllocator.max_size();}
00174 
00175 private:
00176         A m_fallbackAllocator;
00177         T m_array[S];
00178 
00179 #ifndef NDEBUG
00180 public:
00181         FixedSizeAllocatorWithCleanup() : m_allocated(false) {}
00182         bool m_allocated;
00183 #endif
00184 };
00185 
00186 //! a block of memory allocated using A
00187 template <class T, class A = AllocatorWithCleanup<T> >
00188 class SecBlock
00189 {
00190 public:
00191         explicit SecBlock(unsigned int size=0)
00192                 : m_size(size) {m_ptr = m_alloc.allocate(size, NULL);}
00193         SecBlock(const SecBlock<T, A> &t)
00194                 : m_size(t.m_size) {m_ptr = m_alloc.allocate(m_size, NULL); memcpy(m_ptr, t.m_ptr, m_size*sizeof(T));}
00195         SecBlock(const T *t, unsigned int len)
00196                 : m_size(len)
00197         {
00198                 m_ptr = m_alloc.allocate(len, NULL);
00199                 if (t == NULL)
00200                         memset(m_ptr, 0, len*sizeof(T));
00201                 else
00202                         memcpy(m_ptr, t, len*sizeof(T));
00203         }
00204 
00205         ~SecBlock()
00206                 {m_alloc.deallocate(m_ptr, m_size);}
00207 
00208 #if defined(__GNUC__) || defined(__BCPLUSPLUS__)
00209         operator const void *() const
00210                 {return m_ptr;}
00211         operator void *()
00212                 {return m_ptr;}
00213 #endif
00214 #if defined(__GNUC__)   // reduce warnings
00215         operator const void *()
00216                 {return m_ptr;}
00217 #endif
00218 
00219         operator const T *() const
00220                 {return m_ptr;}
00221         operator T *()
00222                 {return m_ptr;}
00223 #if defined(__GNUC__)   // reduce warnings
00224         operator const T *()
00225                 {return m_ptr;}
00226 #endif
00227 
00228         template <typename I>
00229         T *operator +(I offset)
00230                 {return m_ptr+offset;}
00231 
00232         template <typename I>
00233         const T *operator +(I offset) const
00234                 {return m_ptr+offset;}
00235 
00236         template <typename I>
00237         T& operator[](I index)
00238                 {assert(index >= 0 && (unsigned int)index < m_size); return m_ptr[index];}
00239 
00240         template <typename I>
00241         const T& operator[](I index) const
00242                 {assert(index >= 0 && (unsigned int)index < m_size); return m_ptr[index];}
00243 
00244         typedef typename A::pointer iterator;
00245         typedef typename A::const_pointer const_iterator;
00246         typedef typename A::size_type size_type;
00247 
00248         iterator begin()
00249                 {return m_ptr;}
00250         const_iterator begin() const
00251                 {return m_ptr;}
00252         iterator end()
00253                 {return m_ptr+m_size;}
00254         const_iterator end() const
00255                 {return m_ptr+m_size;}
00256 
00257         typename A::pointer data() {return m_ptr;}
00258         typename A::const_pointer data() const {return m_ptr;}
00259 
00260         size_type size() const {return m_size;}
00261         bool empty() const {return m_size == 0;}
00262 
00263         void Assign(const T *t, unsigned int len)
00264         {
00265                 New(len);
00266                 memcpy(m_ptr, t, len*sizeof(T));
00267         }
00268 
00269         void Assign(const SecBlock<T, A> &t)
00270         {
00271                 New(t.m_size);
00272                 memcpy(m_ptr, t.m_ptr, m_size*sizeof(T));
00273         }
00274 
00275         SecBlock& operator=(const SecBlock<T, A> &t)
00276         {
00277                 Assign(t);
00278                 return *this;
00279         }
00280 
00281         bool operator==(const SecBlock<T, A> &t) const
00282         {
00283                 return m_size == t.m_size && memcmp(m_ptr, t.m_ptr, m_size*sizeof(T)) == 0;
00284         }
00285 
00286         bool operator!=(const SecBlock<T, A> &t) const
00287         {
00288                 return !operator==(t);
00289         }
00290 
00291         void New(unsigned int newSize)
00292         {
00293                 m_ptr = m_alloc.reallocate(m_ptr, m_size, newSize, false);
00294                 m_size = newSize;
00295         }
00296 
00297         void CleanNew(unsigned int newSize)
00298         {
00299                 New(newSize);
00300                 memset(m_ptr, 0, m_size*sizeof(T));
00301         }
00302 
00303         void Grow(unsigned int newSize)
00304         {
00305                 if (newSize > m_size)
00306                 {
00307                         m_ptr = m_alloc.reallocate(m_ptr, m_size, newSize, true);
00308                         m_size = newSize;
00309                 }
00310         }
00311 
00312         void CleanGrow(unsigned int newSize)
00313         {
00314                 if (newSize > m_size)
00315                 {
00316                         m_ptr = m_alloc.reallocate(m_ptr, m_size, newSize, true);
00317                         memset(m_ptr+m_size, 0, (newSize-m_size)*sizeof(T));
00318                         m_size = newSize;
00319                 }
00320         }
00321 
00322         void resize(unsigned int newSize)
00323         {
00324                 m_ptr = m_alloc.reallocate(m_ptr, m_size, newSize, true);
00325                 m_size = newSize;
00326         }
00327 
00328         void swap(SecBlock<T, A> &b);
00329 
00330 //private:
00331         A m_alloc;
00332         unsigned int m_size;
00333         T *m_ptr;
00334 };
00335 
00336 template <class T, class A> void SecBlock<T, A>::swap(SecBlock<T, A> &b)
00337 {
00338         std::swap(m_alloc, b.m_alloc);
00339         std::swap(m_size, b.m_size);
00340         std::swap(m_ptr, b.m_ptr);
00341 }
00342 
00343 typedef SecBlock<byte> SecByteBlock;
00344 typedef SecBlock<word> SecWordBlock;
00345 
00346 template <class T, unsigned int S, class A = FixedSizeAllocatorWithCleanup<T, S> >
00347 class FixedSizeSecBlock : public SecBlock<T, A>
00348 {
00349 public:
00350         explicit FixedSizeSecBlock() : SecBlock<T, A>(S) {}
00351 };
00352 
00353 template <class T, unsigned int S, class A = FixedSizeAllocatorWithCleanup<T, S, AllocatorWithCleanup<T> > >
00354 class SecBlockWithHint : public SecBlock<T, A>
00355 {
00356 public:
00357         explicit SecBlockWithHint(unsigned int size) : SecBlock<T, A>(size) {}
00358 };
00359 
00360 template<class T, class U>
00361 inline bool operator==(const CryptoPP::AllocatorWithCleanup<T>&, const CryptoPP::AllocatorWithCleanup<U>&) {return (true);}
00362 template<class T, class U>
00363 inline bool operator!=(const CryptoPP::AllocatorWithCleanup<T>&, const CryptoPP::AllocatorWithCleanup<U>&) {return (false);}
00364 
00365 NAMESPACE_END
00366 
00367 NAMESPACE_BEGIN(std)
00368 template <class T, class A>
00369 inline void swap(CryptoPP::SecBlock<T, A> &a, CryptoPP::SecBlock<T, A> &b)
00370 {
00371         a.swap(b);
00372 }
00373 
00374 #if defined(_STLPORT_VERSION) && !defined(_STLP_MEMBER_TEMPLATE_CLASSES)
00375 template <class _Tp1, class _Tp2>
00376 inline CryptoPP::AllocatorWithCleanup<_Tp2>&
00377 __stl_alloc_rebind(CryptoPP::AllocatorWithCleanup<_Tp1>& __a, const _Tp2*)
00378 {
00379         return (CryptoPP::AllocatorWithCleanup<_Tp2>&)(__a);
00380 }
00381 #endif
00382 
00383 NAMESPACE_END
00384 
00385 #endif

Generated on Mon Apr 19 18:12:32 2004 for Crypto++ by doxygen 1.3.6-20040222