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

Generated on Thu Nov 23 15:57:45 2006 for Crypto++ by  doxygen 1.5.1-p1