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 "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         typedef typename A::value_type value_type;
00207         typedef typename A::pointer iterator;
00208         typedef typename A::const_pointer const_iterator;
00209         typedef typename A::size_type size_type;
00210 
00211     explicit SecBlock(size_type size=0)
00212                 : m_size(size) {m_ptr = m_alloc.allocate(size, NULL);}
00213         SecBlock(const SecBlock<T, A> &t)
00214                 : m_size(t.m_size) {m_ptr = m_alloc.allocate(m_size, NULL); memcpy(m_ptr, t.m_ptr, m_size*sizeof(T));}
00215         SecBlock(const T *t, size_type len)
00216                 : m_size(len)
00217         {
00218                 m_ptr = m_alloc.allocate(len, NULL);
00219                 if (t == NULL)
00220                         memset(m_ptr, 0, len*sizeof(T));
00221                 else
00222                         memcpy(m_ptr, t, len*sizeof(T));
00223         }
00224 
00225         ~SecBlock()
00226                 {m_alloc.deallocate(m_ptr, m_size);}
00227 
00228         operator const void *() const
00229                 {return m_ptr;}
00230         operator void *()
00231                 {return m_ptr;}
00232 #if defined(__GNUC__) && __GNUC__ < 3   // reduce warnings
00233         operator const void *()
00234                 {return m_ptr;}
00235 #endif
00236 
00237         operator const T *() const
00238                 {return m_ptr;}
00239         operator T *()
00240                 {return m_ptr;}
00241 #if defined(__GNUC__) && __GNUC__ < 3   // reduce warnings
00242         operator const T *()
00243                 {return m_ptr;}
00244 #endif
00245 
00246 //      T *operator +(size_type offset)
00247 //              {return m_ptr+offset;}
00248 
00249 //      const T *operator +(size_type offset) const
00250 //              {return m_ptr+offset;}
00251 
00252 //      T& operator[](size_type index)
00253 //              {assert(index >= 0 && index < m_size); return m_ptr[index];}
00254 
00255 //      const T& operator[](size_type index) const
00256 //              {assert(index >= 0 && index < m_size); return m_ptr[index];}
00257 
00258         iterator begin()
00259                 {return m_ptr;}
00260         const_iterator begin() const
00261                 {return m_ptr;}
00262         iterator end()
00263                 {return m_ptr+m_size;}
00264         const_iterator end() const
00265                 {return m_ptr+m_size;}
00266 
00267         typename A::pointer data() {return m_ptr;}
00268         typename A::const_pointer data() const {return m_ptr;}
00269 
00270         size_type size() const {return m_size;}
00271         bool empty() const {return m_size == 0;}
00272 
00273         void Assign(const T *t, size_type len)
00274         {
00275                 New(len);
00276                 memcpy(m_ptr, t, len*sizeof(T));
00277         }
00278 
00279         void Assign(const SecBlock<T, A> &t)
00280         {
00281                 New(t.m_size);
00282                 memcpy(m_ptr, t.m_ptr, m_size*sizeof(T));
00283         }
00284 
00285         SecBlock<T, A>& operator=(const SecBlock<T, A> &t)
00286         {
00287                 Assign(t);
00288                 return *this;
00289         }
00290 
00291         SecBlock<T, A>& operator+=(const SecBlock<T, A> &t)
00292         {
00293                 size_type oldSize = m_size;
00294                 Grow(m_size+t.m_size);
00295                 memcpy(m_ptr+oldSize, t.m_ptr, t.m_size*sizeof(T));
00296                 return *this;
00297         }
00298 
00299         SecBlock<T, A> operator+(const SecBlock<T, A> &t)
00300         {
00301                 SecBlock<T, A> result(m_size+t.m_size);
00302                 memcpy(result.m_ptr, m_ptr, m_size*sizeof(T));
00303                 memcpy(result.m_ptr+m_size, t.m_ptr, t.m_size*sizeof(T));
00304                 return result;
00305         }
00306 
00307         bool operator==(const SecBlock<T, A> &t) const
00308         {
00309                 return m_size == t.m_size && memcmp(m_ptr, t.m_ptr, m_size*sizeof(T)) == 0;
00310         }
00311 
00312         bool operator!=(const SecBlock<T, A> &t) const
00313         {
00314                 return !operator==(t);
00315         }
00316 
00317         void New(size_type newSize)
00318         {
00319                 m_ptr = m_alloc.reallocate(m_ptr, m_size, newSize, false);
00320                 m_size = newSize;
00321         }
00322 
00323         void CleanNew(size_type newSize)
00324         {
00325                 New(newSize);
00326                 memset(m_ptr, 0, m_size*sizeof(T));
00327         }
00328 
00329         void Grow(size_type newSize)
00330         {
00331                 if (newSize > m_size)
00332                 {
00333                         m_ptr = m_alloc.reallocate(m_ptr, m_size, newSize, true);
00334                         m_size = newSize;
00335                 }
00336         }
00337 
00338         void CleanGrow(size_type newSize)
00339         {
00340                 if (newSize > m_size)
00341                 {
00342                         m_ptr = m_alloc.reallocate(m_ptr, m_size, newSize, true);
00343                         memset(m_ptr+m_size, 0, (newSize-m_size)*sizeof(T));
00344                         m_size = newSize;
00345                 }
00346         }
00347 
00348         void resize(size_type newSize)
00349         {
00350                 m_ptr = m_alloc.reallocate(m_ptr, m_size, newSize, true);
00351                 m_size = newSize;
00352         }
00353 
00354         void swap(SecBlock<T, A> &b)
00355         {
00356                 std::swap(m_alloc, b.m_alloc);
00357                 std::swap(m_size, b.m_size);
00358                 std::swap(m_ptr, b.m_ptr);
00359         }
00360 
00361 //private:
00362         A m_alloc;
00363         size_type m_size;
00364         T *m_ptr;
00365 };
00366 
00367 typedef SecBlock<byte> SecByteBlock;
00368 typedef SecBlock<word> SecWordBlock;
00369 
00370 template <class T, unsigned int S, class A = FixedSizeAllocatorWithCleanup<T, S> >
00371 class FixedSizeSecBlock : public SecBlock<T, A>
00372 {
00373 public:
00374         explicit FixedSizeSecBlock() : SecBlock<T, A>(S) {}
00375 };
00376 
00377 template <class T, unsigned int S, class A = FixedSizeAllocatorWithCleanup<T, S, AllocatorWithCleanup<T> > >
00378 class SecBlockWithHint : public SecBlock<T, A>
00379 {
00380 public:
00381         explicit SecBlockWithHint(size_t size) : SecBlock<T, A>(size) {}
00382 };
00383 
00384 template<class T, class U>
00385 inline bool operator==(const CryptoPP::AllocatorWithCleanup<T>&, const CryptoPP::AllocatorWithCleanup<U>&) {return (true);}
00386 template<class T, class U>
00387 inline bool operator!=(const CryptoPP::AllocatorWithCleanup<T>&, const CryptoPP::AllocatorWithCleanup<U>&) {return (false);}
00388 
00389 NAMESPACE_END
00390 
00391 NAMESPACE_BEGIN(std)
00392 template <class T, class A>
00393 inline void swap(CryptoPP::SecBlock<T, A> &a, CryptoPP::SecBlock<T, A> &b)
00394 {
00395         a.swap(b);
00396 }
00397 
00398 #if defined(_STLPORT_VERSION) && !defined(_STLP_MEMBER_TEMPLATE_CLASSES)
00399 template <class _Tp1, class _Tp2>
00400 inline CryptoPP::AllocatorWithCleanup<_Tp2>&
00401 __stl_alloc_rebind(CryptoPP::AllocatorWithCleanup<_Tp1>& __a, const _Tp2*)
00402 {
00403         return (CryptoPP::AllocatorWithCleanup<_Tp2>&)(__a);
00404 }
00405 #endif
00406 
00407 NAMESPACE_END
00408 
00409 #endif

Generated on Tue Aug 16 08:38:43 2005 for Crypto++ by  doxygen 1.3.9.1