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

Generated on Wed Jul 21 19:15:33 2004 for Crypto++ by doxygen 1.3.7-20040704