00001 // secblock.h - written and placed in the public domain by Wei Dai 00002 00003 //! \file secblock.h 00004 //! \brief Classes and functions for secure memory allocations. 00005 00006 #ifndef CRYPTOPP_SECBLOCK_H 00007 #define CRYPTOPP_SECBLOCK_H 00008 00009 #include "config.h" 00010 #include "stdcpp.h" 00011 #include "misc.h" 00012 00013 #if CRYPTOPP_MSC_VERSION 00014 # pragma warning(push) 00015 # pragma warning(disable: 4700) 00016 # if (CRYPTOPP_MSC_VERSION >= 1400) 00017 # pragma warning(disable: 6386) 00018 # endif 00019 #endif 00020 00021 NAMESPACE_BEGIN(CryptoPP) 00022 00023 // ************** secure memory allocation *************** 00024 00025 //! \class AllocatorBase 00026 //! \brief Base class for all allocators used by SecBlock 00027 //! \tparam T the class or type 00028 template<class T> 00029 class AllocatorBase 00030 { 00031 public: 00032 typedef T value_type; 00033 typedef size_t size_type; 00034 #ifdef CRYPTOPP_MSVCRT6 00035 typedef ptrdiff_t difference_type; 00036 #else 00037 typedef std::ptrdiff_t difference_type; 00038 #endif 00039 typedef T * pointer; 00040 typedef const T * const_pointer; 00041 typedef T & reference; 00042 typedef const T & const_reference; 00043 00044 pointer address(reference r) const {return (&r);} 00045 const_pointer address(const_reference r) const {return (&r); } 00046 void construct(pointer p, const T& val) {new (p) T(val);} 00047 void destroy(pointer p) {CRYPTOPP_UNUSED(p); p->~T();} 00048 00049 //! \brief Returns the maximum number of elements the allocator can provide 00050 //! \returns the maximum number of elements the allocator can provide 00051 //! \details Internally, preprocessor macros are used rather than std::numeric_limits 00052 //! because the latter is \a not a \a constexpr. Some compilers, like Clang, do not 00053 //! optimize it well under all circumstances. Compilers like GCC, ICC and MSVC appear 00054 //! to optimize it well in either form. 00055 size_type max_size() const {return (SIZE_MAX/sizeof(T));} 00056 00057 #if defined(CRYPTOPP_CXX11_VARIADIC_TEMPLATES) || defined(CRYPTOPP_DOXYGEN_PROCESSING) 00058 00059 //! \brief Constructs a new U using variadic arguments 00060 //! \tparam U the type to be forwarded 00061 //! \tparam Args the arguments to be forwarded 00062 //! \param ptr pointer to type U 00063 //! \param args variadic arguments 00064 //! \details This is a C++11 feature. It is available when CRYPTOPP_CXX11_VARIADIC_TEMPLATES 00065 //! is defined. The define is controlled by compiler versions detected in config.h. 00066 template<typename U, typename... Args> 00067 void construct(U* ptr, Args&&... args) {::new ((void*)ptr) U(std::forward<Args>(args)...);} 00068 00069 //! \brief Destroys an U constructed with variadic arguments 00070 //! \tparam U the type to be forwarded 00071 //! \details This is a C++11 feature. It is available when CRYPTOPP_CXX11_VARIADIC_TEMPLATES 00072 //! is defined. The define is controlled by compiler versions detected in config.h. 00073 template<typename U> 00074 void destroy(U* ptr) {if(ptr) ptr->~U();} 00075 00076 #endif 00077 00078 protected: 00079 00080 //! \brief Verifies the allocator can satisfy a request based on size 00081 //! \param size the number of elements 00082 //! \throws InvalidArgument 00083 //! \details CheckSize verifies the number of elements requested is valid. 00084 //! \details If size is greater than max_size(), then InvalidArgument is thrown. 00085 //! The library throws InvalidArgument if the size is too large to satisfy. 00086 //! \details Internally, preprocessor macros are used rather than std::numeric_limits 00087 //! because the latter is \a not a \a constexpr. Some compilers, like Clang, do not 00088 //! optimize it well under all circumstances. Compilers like GCC, ICC and MSVC appear 00089 //! to optimize it well in either form. 00090 //! \note size is the count of elements, and not the number of bytes 00091 static void CheckSize(size_t size) 00092 { 00093 // C++ throws std::bad_alloc (C++03) or std::bad_array_new_length (C++11) here. 00094 if (size > (SIZE_MAX/sizeof(T))) 00095 throw InvalidArgument("AllocatorBase: requested size would cause integer overflow"); 00096 } 00097 }; 00098 00099 #define CRYPTOPP_INHERIT_ALLOCATOR_TYPES \ 00100 typedef typename AllocatorBase<T>::value_type value_type;\ 00101 typedef typename AllocatorBase<T>::size_type size_type;\ 00102 typedef typename AllocatorBase<T>::difference_type difference_type;\ 00103 typedef typename AllocatorBase<T>::pointer pointer;\ 00104 typedef typename AllocatorBase<T>::const_pointer const_pointer;\ 00105 typedef typename AllocatorBase<T>::reference reference;\ 00106 typedef typename AllocatorBase<T>::const_reference const_reference; 00107 00108 //! \brief Reallocation function 00109 //! \tparam T the class or type 00110 //! \tparam A the class or type's allocator 00111 //! \param alloc the allocator 00112 //! \param oldPtr the previous allocation 00113 //! \param oldSize the size of the previous allocation 00114 //! \param newSize the new, requested size 00115 //! \param preserve flag that indicates if the old allocation should be preserved 00116 //! \note oldSize and newSize are the count of elements, and not the 00117 //! number of bytes. 00118 template <class T, class A> 00119 typename A::pointer StandardReallocate(A& alloc, T *oldPtr, typename A::size_type oldSize, typename A::size_type newSize, bool preserve) 00120 { 00121 assert((oldPtr && oldSize) || !(oldPtr || oldSize)); 00122 if (oldSize == newSize) 00123 return oldPtr; 00124 00125 if (preserve) 00126 { 00127 typename A::pointer newPointer = alloc.allocate(newSize, NULL); 00128 const size_t copySize = STDMIN(oldSize, newSize) * sizeof(T); 00129 00130 if (oldPtr && newPointer) {memcpy_s(newPointer, copySize, oldPtr, copySize);} 00131 alloc.deallocate(oldPtr, oldSize); 00132 return newPointer; 00133 } 00134 else 00135 { 00136 alloc.deallocate(oldPtr, oldSize); 00137 return alloc.allocate(newSize, NULL); 00138 } 00139 } 00140 00141 //! \class AllocatorWithCleanup 00142 //! \brief Allocates a block of memory with cleanup 00143 //! \tparam T class or type 00144 //! \tparam T_Align16 boolean that determines whether allocations should be aligned on 16-byte boundaries 00145 //! \details If T_Align16 is true, then AllocatorWithCleanup calls AlignedAllocate() 00146 //! for memory allocations. If T_Align16 is false, then AllocatorWithCleanup() calls 00147 //! UnalignedAllocate() for memory allocations. 00148 //! \details Template parameter T_Align16 is effectively controlled by cryptlib.h and mirrors 00149 //! CRYPTOPP_BOOL_ALIGN16. CRYPTOPP_BOOL_ALIGN16 is often used as the template parameter. 00150 template <class T, bool T_Align16 = false> 00151 class AllocatorWithCleanup : public AllocatorBase<T> 00152 { 00153 public: 00154 CRYPTOPP_INHERIT_ALLOCATOR_TYPES 00155 00156 //! \brief Allocates a block of memory 00157 //! \param ptr the size of the allocation 00158 //! \param size the size of the allocation 00159 //! \returns a memory block 00160 //! \throws InvalidArgument 00161 //! \details allocate() first checks the size of the request. If it is non-0 00162 //! and less than max_size(), then an attempt is made to fulfill the request using either 00163 //! AlignedAllocate() or UnalignedAllocate(). 00164 //! \details AlignedAllocate() is used if T_Align16 is true. 00165 //! UnalignedAllocate() used if T_Align16 is false. 00166 //! \details This is the C++ *Placement New* operator. ptr is not used, and the function 00167 //! asserts in Debug builds if ptr is non-NULL. 00168 //! \sa CallNewHandler() for the methods used to recover from a failed 00169 //! allocation attempt. 00170 //! \note size is the count of elements, and not the number of bytes 00171 pointer allocate(size_type size, const void *ptr = NULL) 00172 { 00173 CRYPTOPP_UNUSED(ptr); assert(ptr == NULL); 00174 this->CheckSize(size); 00175 if (size == 0) 00176 return NULL; 00177 00178 #if CRYPTOPP_BOOL_ALIGN16 00179 // TODO: should this need the test 'size*sizeof(T) >= 16'? 00180 if (T_Align16 && size*sizeof(T) >= 16) 00181 return (pointer)AlignedAllocate(size*sizeof(T)); 00182 #endif 00183 00184 return (pointer)UnalignedAllocate(size*sizeof(T)); 00185 } 00186 00187 //! \brief Deallocates a block of memory 00188 //! \param ptr the size of the allocation 00189 //! \param size the size of the allocation 00190 //! \details Internally, SecureWipeArray() is called before deallocating the memory. 00191 //! Once the memory block is wiped or zeroized, AlignedDeallocate() or 00192 //! UnalignedDeallocate() is called. 00193 //! \details AlignedDeallocate() is used if T_Align16 is true. 00194 //! UnalignedDeallocate() used if T_Align16 is false. 00195 void deallocate(void *ptr, size_type size) 00196 { 00197 assert((ptr && size) || !(ptr || size)); 00198 SecureWipeArray((pointer)ptr, size); 00199 00200 #if CRYPTOPP_BOOL_ALIGN16 00201 if (T_Align16 && size*sizeof(T) >= 16) 00202 return AlignedDeallocate(ptr); 00203 #endif 00204 00205 UnalignedDeallocate(ptr); 00206 } 00207 00208 //! \brief Reallocates a block of memory 00209 //! \param oldPtr the previous allocation 00210 //! \param oldSize the size of the previous allocation 00211 //! \param newSize the new, requested size 00212 //! \param preserve flag that indicates if the old allocation should be preserved 00213 //! \returns pointer to the new memory block 00214 //! \details Internally, reallocate() calls StandardReallocate(). 00215 //! \details If preserve is true, then index 0 is used to begin copying the 00216 //! old memory block to the new one. If the block grows, then the old array 00217 //! is copied in its entirety. If the block shrinks, then only newSize 00218 //! elements are copied from the old block to the new one. 00219 //! \note oldSize and newSize are the count of elements, and not the 00220 //! number of bytes. 00221 pointer reallocate(T *oldPtr, size_type oldSize, size_type newSize, bool preserve) 00222 { 00223 assert((oldPtr && oldSize) || !(oldPtr || oldSize)); 00224 return StandardReallocate(*this, oldPtr, oldSize, newSize, preserve); 00225 } 00226 00227 // VS.NET STL enforces the policy of "All STL-compliant allocators have to provide a 00228 // template class member called rebind". 00229 template <class U> struct rebind { typedef AllocatorWithCleanup<U, T_Align16> other; }; 00230 #if _MSC_VER >= 1500 00231 AllocatorWithCleanup() {} 00232 template <class U, bool A> AllocatorWithCleanup(const AllocatorWithCleanup<U, A> &) {} 00233 #endif 00234 }; 00235 00236 CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup<byte>; 00237 CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup<word16>; 00238 CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup<word32>; 00239 CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup<word64>; 00240 #if CRYPTOPP_BOOL_X86 00241 CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup<word, true>; // for Integer 00242 #endif 00243 00244 //! \class NullAllocator 00245 //! \brief NULL allocator 00246 //! \tparam T class or type 00247 //! \details A NullAllocator is useful for fixed-size, stack based allocations 00248 //! (i.e., static arrays used by FixedSizeAllocatorWithCleanup). 00249 //! \details A NullAllocator always returns 0 for max_size(), and always returns 00250 //! NULL for allocation requests. Though the allocator does not allocate at 00251 //! runtime, it does perform a secure wipe or zeroization during cleanup. 00252 template <class T> 00253 class NullAllocator : public AllocatorBase<T> 00254 { 00255 public: 00256 CRYPTOPP_INHERIT_ALLOCATOR_TYPES 00257 00258 // TODO: should this return NULL or throw bad_alloc? Non-Windows C++ standard 00259 // libraries always throw. And late mode Windows throws. Early model Windows 00260 // (circa VC++ 6.0) returned NULL. 00261 pointer allocate(size_type n, const void* unused = NULL) 00262 { 00263 CRYPTOPP_UNUSED(n); CRYPTOPP_UNUSED(unused); 00264 assert(false); return NULL; 00265 } 00266 00267 void deallocate(void *p, size_type n) 00268 { 00269 CRYPTOPP_UNUSED(p); CRYPTOPP_UNUSED(n); 00270 assert(false); 00271 } 00272 00273 size_type max_size() const {return 0;} 00274 }; 00275 00276 //! \class FixedSizeAllocatorWithCleanup 00277 //! \brief Static secure memory block with cleanup 00278 //! \tparam T class or type 00279 //! \tparam S fixed-size of the stack-based memory block 00280 //! \tparam A AllocatorBase derived class for allocation and cleanup 00281 //! \details FixedSizeAllocatorWithCleanup provides a fixed-size, stack- 00282 //! based allocation at compile time. The class can grow its memory 00283 //! block at runtime if a suitable allocator is available. If size 00284 //! grows beyond S and a suitable allocator is available, then the 00285 //! statically allocated array is obsoleted. 00286 //! \note This allocator can't be used with standard collections because 00287 //! they require that all objects of the same allocator type are equivalent. 00288 template <class T, size_t S, class A = NullAllocator<T>, bool T_Align16 = false> 00289 class FixedSizeAllocatorWithCleanup : public AllocatorBase<T> 00290 { 00291 public: 00292 CRYPTOPP_INHERIT_ALLOCATOR_TYPES 00293 00294 //! \brief Constructs a FixedSizeAllocatorWithCleanup 00295 FixedSizeAllocatorWithCleanup() : m_allocated(false) {} 00296 00297 //! \brief Allocates a block of memory 00298 //! \param size size of the memory block 00299 //! \details FixedSizeAllocatorWithCleanup provides a fixed-size, stack- 00300 //! based allocation at compile time. If size is less than or equal to 00301 //! S, then a pointer to the static array is returned. 00302 //! \details The class can grow its memory block at runtime if a suitable 00303 //! allocator is available. If size grows beyond S and a suitable 00304 //! allocator is available, then the statically allocated array is 00305 //! obsoleted. If a suitable allocator is \a not available, as with a 00306 //! NullAllocator, then the function returns NULL and a runtime error 00307 //! eventually occurs. 00308 //! \note size is the count of elements, and not the number of bytes. 00309 //! \sa reallocate(), SecBlockWithHint 00310 pointer allocate(size_type size) 00311 { 00312 assert(IsAlignedOn(m_array, 8)); 00313 00314 if (size <= S && !m_allocated) 00315 { 00316 m_allocated = true; 00317 return GetAlignedArray(); 00318 } 00319 else 00320 return m_fallbackAllocator.allocate(size); 00321 } 00322 00323 //! \brief Allocates a block of memory 00324 //! \param size size of the memory block 00325 //! \param hint an unused hint 00326 //! \details FixedSizeAllocatorWithCleanup provides a fixed-size, stack- 00327 //! based allocation at compile time. If size is less than or equal to 00328 //! S, then a pointer to the static array is returned. 00329 //! \details The class can grow its memory block at runtime if a suitable 00330 //! allocator is available. If size grows beyond S and a suitable 00331 //! allocator is available, then the statically allocated array is 00332 //! obsoleted. If a suitable allocator is \a not available, as with a 00333 //! NullAllocator, then the function returns NULL and a runtime error 00334 //! eventually occurs. 00335 //! \note size is the count of elements, and not the number of bytes. 00336 //! \sa reallocate(), SecBlockWithHint 00337 pointer allocate(size_type size, const void *hint) 00338 { 00339 if (size <= S && !m_allocated) 00340 { 00341 m_allocated = true; 00342 return GetAlignedArray(); 00343 } 00344 else 00345 return m_fallbackAllocator.allocate(size, hint); 00346 } 00347 00348 //! \brief Deallocates a block of memory 00349 //! \param ptr a pointer to the memory block to deallocate 00350 //! \param size size of the memory block 00351 //! \details The memory block is wiped or zeroized before deallocation. 00352 //! If the statically allocated memory block is active, then no 00353 //! additional actions are taken after the wipe. 00354 //! \details If a dynamic memory block is active, then the pointer and 00355 //! size are passed to the allocator for deallocation. 00356 void deallocate(void *ptr, size_type size) 00357 { 00358 if (ptr == GetAlignedArray()) 00359 { 00360 assert(size <= S); 00361 assert(m_allocated); 00362 m_allocated = false; 00363 SecureWipeArray((pointer)ptr, size); 00364 } 00365 else 00366 m_fallbackAllocator.deallocate(ptr, size); 00367 } 00368 00369 //! \brief Reallocates a block of memory 00370 //! \param oldPtr the previous allocation 00371 //! \param oldSize the size of the previous allocation 00372 //! \param newSize the new, requested size 00373 //! \param preserve flag that indicates if the old allocation should be preserved 00374 //! \returns pointer to the new memory block 00375 //! \details FixedSizeAllocatorWithCleanup provides a fixed-size, stack- 00376 //! based allocation at compile time. If size is less than or equal to 00377 //! S, then a pointer to the static array is returned. 00378 //! \details The class can grow its memory block at runtime if a suitable 00379 //! allocator is available. If size grows beyond S and a suitable 00380 //! allocator is available, then the statically allocated array is 00381 //! obsoleted. If a suitable allocator is \a not available, as with a 00382 //! NullAllocator, then the function returns NULL and a runtime error 00383 //! eventually occurs. 00384 //! \note size is the count of elements, and not the number of bytes. 00385 //! \sa reallocate(), SecBlockWithHint 00386 pointer reallocate(pointer oldPtr, size_type oldSize, size_type newSize, bool preserve) 00387 { 00388 if (oldPtr == GetAlignedArray() && newSize <= S) 00389 { 00390 assert(oldSize <= S); 00391 if (oldSize > newSize) 00392 SecureWipeArray(oldPtr+newSize, oldSize-newSize); 00393 return oldPtr; 00394 } 00395 00396 pointer newPointer = allocate(newSize, NULL); 00397 if (preserve && newSize) 00398 { 00399 const size_t copySize = STDMIN(oldSize, newSize); 00400 memcpy_s(newPointer, copySize, oldPtr, copySize); 00401 } 00402 deallocate(oldPtr, oldSize); 00403 return newPointer; 00404 } 00405 00406 size_type max_size() const {return STDMAX(m_fallbackAllocator.max_size(), S);} 00407 00408 private: 00409 #ifdef __BORLANDC__ 00410 T* GetAlignedArray() {return m_array;} 00411 T m_array[S]; 00412 #else 00413 T* GetAlignedArray() {return (CRYPTOPP_BOOL_ALIGN16 && T_Align16) ? (T*)(((byte *)m_array) + (0-(size_t)m_array)%16) : m_array;} 00414 CRYPTOPP_ALIGN_DATA(8) T m_array[(CRYPTOPP_BOOL_ALIGN16 && T_Align16) ? S+8/sizeof(T) : S]; 00415 #endif 00416 A m_fallbackAllocator; 00417 bool m_allocated; 00418 }; 00419 00420 //! \class SecBlock 00421 //! \brief Secure memory block with allocator and cleanup 00422 //! \tparam T a class or type 00423 //! \tparam A AllocatorWithCleanup derived class for allocation and cleanup 00424 template <class T, class A = AllocatorWithCleanup<T> > 00425 class SecBlock 00426 { 00427 public: 00428 typedef typename A::value_type value_type; 00429 typedef typename A::pointer iterator; 00430 typedef typename A::const_pointer const_iterator; 00431 typedef typename A::size_type size_type; 00432 00433 //! \brief Construct a SecBlock with space for size elements. 00434 //! \param size the number of elements in the allocation 00435 //! \throws std::bad_alloc 00436 //! \details The elements are not initialized. 00437 //! \note size is the count of elements, and not the number of bytes 00438 explicit SecBlock(size_type size=0) 00439 : m_size(size), m_ptr(m_alloc.allocate(size, NULL)) { } 00440 00441 //! \brief Copy construct a SecBlock from another SecBlock 00442 //! \param t the other SecBlock 00443 //! \throws std::bad_alloc 00444 SecBlock(const SecBlock<T, A> &t) 00445 : m_size(t.m_size), m_ptr(m_alloc.allocate(t.m_size, NULL)) { 00446 assert((!t.m_ptr && !m_size) || (t.m_ptr && m_size)); 00447 if (t.m_ptr) {memcpy_s(m_ptr, m_size*sizeof(T), t.m_ptr, t.m_size*sizeof(T));} 00448 } 00449 00450 //! \brief Construct a SecBlock from an array of elements. 00451 //! \param ptr a pointer to an array of T 00452 //! \param len the number of elements in the memory block 00453 //! \throws std::bad_alloc 00454 //! \details If <tt>ptr!=NULL</tt> and <tt>len!=0</tt>, then the block is initialized from the pointer ptr. 00455 //! If <tt>ptr==NULL</tt> and <tt>len!=0</tt>, then the block is initialized to 0. 00456 //! Otherwise, the block is empty and uninitialized. 00457 //! \note size is the count of elements, and not the number of bytes 00458 SecBlock(const T *ptr, size_type len) 00459 : m_size(len), m_ptr(m_alloc.allocate(len, NULL)) { 00460 assert((!m_ptr && !m_size) || (m_ptr && m_size)); 00461 if (ptr && m_ptr) 00462 memcpy_s(m_ptr, m_size*sizeof(T), ptr, len*sizeof(T)); 00463 else if (m_size) 00464 memset(m_ptr, 0, m_size*sizeof(T)); 00465 } 00466 00467 ~SecBlock() 00468 {m_alloc.deallocate(m_ptr, m_size);} 00469 00470 #ifdef __BORLANDC__ 00471 operator T *() const 00472 {return (T*)m_ptr;} 00473 #else 00474 operator const void *() const 00475 {return m_ptr;} 00476 operator void *() 00477 {return m_ptr;} 00478 00479 operator const T *() const 00480 {return m_ptr;} 00481 operator T *() 00482 {return m_ptr;} 00483 #endif 00484 00485 //! \brief Provides an iterator pointing to the first element in the memory block 00486 //! \returns iterator pointing to the first element in the memory block 00487 iterator begin() 00488 {return m_ptr;} 00489 //! \brief Provides a constant iterator pointing to the first element in the memory block 00490 //! \returns constant iterator pointing to the first element in the memory block 00491 const_iterator begin() const 00492 {return m_ptr;} 00493 //! \brief Provides an iterator pointing beyond the last element in the memory block 00494 //! \returns iterator pointing beyond the last element in the memory block 00495 iterator end() 00496 {return m_ptr+m_size;} 00497 //! \brief Provides a constant iterator pointing beyond the last element in the memory block 00498 //! \returns constant iterator pointing beyond the last element in the memory block 00499 const_iterator end() const 00500 {return m_ptr+m_size;} 00501 00502 //! \brief Provides a pointer to the first element in the memory block 00503 //! \returns pointer to the first element in the memory block 00504 typename A::pointer data() {return m_ptr;} 00505 //! \brief Provides a pointer to the first element in the memory block 00506 //! \returns constant pointer to the first element in the memory block 00507 typename A::const_pointer data() const {return m_ptr;} 00508 00509 //! \brief Provides the count of elements in the SecBlock 00510 //! \returns number of elements in the memory block 00511 //! \note the return value is the count of elements, and not the number of bytes 00512 size_type size() const {return m_size;} 00513 //! \brief Determines if the SecBlock is empty 00514 //! \returns true if number of elements in the memory block is 0, false otherwise 00515 bool empty() const {return m_size == 0;} 00516 00517 //! \brief Provides a byte pointer to the first element in the memory block 00518 //! \returns byte pointer to the first element in the memory block 00519 byte * BytePtr() {return (byte *)m_ptr;} 00520 //! \brief Return a byte pointer to the first element in the memory block 00521 //! \returns constant byte pointer to the first element in the memory block 00522 const byte * BytePtr() const {return (const byte *)m_ptr;} 00523 //! \brief Provides the number of bytes in the SecBlock 00524 //! \return the number of bytes in the memory block 00525 //! \note the return value is the number of bytes, and not count of elements. 00526 size_type SizeInBytes() const {return m_size*sizeof(T);} 00527 00528 //! \brief Set contents and size from an array 00529 //! \param ptr a pointer to an array of T 00530 //! \param len the number of elements in the memory block 00531 //! \details If the memory block is reduced in size, then the unused area is set to 0. 00532 void Assign(const T *ptr, size_type len) 00533 { 00534 New(len); 00535 if (m_ptr && ptr && len) 00536 {memcpy_s(m_ptr, m_size*sizeof(T), ptr, len*sizeof(T));} 00537 } 00538 00539 //! \brief Copy contents from another SecBlock 00540 //! \param t the other SecBlock 00541 //! \details Assign checks for self assignment. 00542 //! \details If the memory block is reduced in size, then the unused area is set to 0. 00543 void Assign(const SecBlock<T, A> &t) 00544 { 00545 if (this != &t) 00546 { 00547 New(t.m_size); 00548 if (m_ptr && t.m_ptr && t.m_size) 00549 {memcpy_s(m_ptr, m_size*sizeof(T), t, t.m_size*sizeof(T));} 00550 } 00551 } 00552 00553 //! \brief Assign contents from another SecBlock 00554 //! \param t the other SecBlock 00555 //! \details Internally, operator=() calls Assign(). 00556 //! \details If the memory block is reduced in size, then the unused area is set to 0. 00557 SecBlock<T, A>& operator=(const SecBlock<T, A> &t) 00558 { 00559 // Assign guards for self-assignment 00560 Assign(t); 00561 return *this; 00562 } 00563 00564 //! \brief Append contents from another SecBlock 00565 //! \param t the other SecBlock 00566 //! \details Internally, this SecBlock calls Grow and then copies the new content. 00567 //! \details If the memory block is reduced in size, then the unused area is set to 0. 00568 SecBlock<T, A>& operator+=(const SecBlock<T, A> &t) 00569 { 00570 assert((!t.m_ptr && !t.m_size) || (t.m_ptr && t.m_ptr.m_size)); 00571 00572 if(t.size) 00573 { 00574 size_type oldSize = m_size; 00575 Grow(m_size+t.m_size); 00576 00577 if (m_ptr && t.m_ptr) 00578 {memcpy_s(m_ptr+oldSize, (m_size-oldSize)*sizeof(T), t.m_ptr, t.m_size*sizeof(T));} 00579 } 00580 return *this; 00581 } 00582 00583 //! \brief Concatenate contents from another SecBlock 00584 //! \param t the other SecBlock 00585 //! \returns a newly constructed SecBlock that is a conacentation of this and t 00586 //! \details Internally, a temporary SecBlock is created and the content from this 00587 //! SecBlock and the other SecBlock are concatenated. The temporary 00588 //! SecBlock is returned to the caller. 00589 SecBlock<T, A> operator+(const SecBlock<T, A> &t) 00590 { 00591 assert((!m_ptr && !m_size) || (m_ptr && m_size)); 00592 assert((!t.m_ptr && !t.m_size) || (t.m_ptr && t.m_ptr.m_size)); 00593 if(!t.size) return SecBlock(*this); 00594 00595 SecBlock<T, A> result(m_size+t.m_size); 00596 memcpy_s(result.m_ptr, result.m_size*sizeof(T), m_ptr, m_size*sizeof(T)); 00597 memcpy_s(result.m_ptr+m_size, (t.m_size-m_size)*sizeof(T), t.m_ptr, t.m_size*sizeof(T)); 00598 return result; 00599 } 00600 00601 //! \brief Bitwise compare two SecBlocks 00602 //! \param t the other SecBlock 00603 //! \returns true if the size and bits are equal, false otherwise 00604 //! \details Uses a constant time compare if the arrays are equal size. The constant time 00605 //! compare is VerifyBufsEqual() found in misc.h. 00606 //! \sa operator!=() 00607 bool operator==(const SecBlock<T, A> &t) const 00608 { 00609 return m_size == t.m_size && VerifyBufsEqual(m_ptr, t.m_ptr, m_size*sizeof(T)); 00610 } 00611 00612 //! \brief Bitwise compare two SecBlocks 00613 //! \param t the other SecBlock 00614 //! \returns true if the size and bits are equal, false otherwise 00615 //! \details Uses a constant time compare if the arrays are equal size. The constant time 00616 //! compare is VerifyBufsEqual() found in misc.h. 00617 //! \details Internally, operator!=() returns the inverse of operator==(). 00618 //! \sa operator==() 00619 bool operator!=(const SecBlock<T, A> &t) const 00620 { 00621 return !operator==(t); 00622 } 00623 00624 //! \brief Change size without preserving contents 00625 //! \param newSize the new size of the memory block 00626 //! \details Old content is \a not preserved. If the memory block is reduced in size, 00627 //! then the unused content is set to 0. If the memory block grows in size, then 00628 //! all content is uninitialized. 00629 //! \details Internally, this SecBlock calls reallocate(). 00630 //! \sa New(), CleanNew(), Grow(), CleanGrow(), resize() 00631 void New(size_type newSize) 00632 { 00633 m_ptr = m_alloc.reallocate(m_ptr, m_size, newSize, false); 00634 m_size = newSize; 00635 } 00636 00637 //! \brief Change size without preserving contents 00638 //! \param newSize the new size of the memory block 00639 //! \details Old content is not preserved. If the memory block is reduced in size, 00640 //! then the unused content is set to 0. Existing and new content is set to 0. 00641 //! \details Internally, this SecBlock calls reallocate(). 00642 //! \sa New(), CleanNew(), Grow(), CleanGrow(), resize() 00643 void CleanNew(size_type newSize) 00644 { 00645 New(newSize); 00646 if (m_ptr) {memset_z(m_ptr, 0, m_size*sizeof(T));} 00647 } 00648 00649 //! \brief Change size and preserve contents 00650 //! \param newSize the new size of the memory block 00651 //! \details Old content is preserved. If the memory block grows in size, then 00652 //! all content is uninitialized. 00653 //! \details Internally, this SecBlock calls reallocate(). 00654 //! \note reallocate() is called if the size increases. If the size does not 00655 //! increase, then Grow does not take action. If the size must change, 00656 //! then use resize(). 00657 //! \sa New(), CleanNew(), Grow(), CleanGrow(), resize() 00658 void Grow(size_type newSize) 00659 { 00660 if (newSize > m_size) 00661 { 00662 m_ptr = m_alloc.reallocate(m_ptr, m_size, newSize, true); 00663 m_size = newSize; 00664 } 00665 } 00666 00667 //! \brief Change size and preserve contents 00668 //! \param newSize the new size of the memory block 00669 //! \details Old content is preserved. If the memory block is reduced in size, 00670 //! then the unused content is set to 0. If the memory block grows in size, 00671 //! then the new content is uninitialized. 00672 //! \details Internally, this SecBlock calls reallocate(). 00673 //! \note reallocate() is called if the size increases. If the size does not 00674 //! increase, then Grow does not take action. If the size must change, 00675 //! then use resize(). 00676 //! \sa New(), CleanNew(), Grow(), CleanGrow(), resize() 00677 void CleanGrow(size_type newSize) 00678 { 00679 if (newSize > m_size) 00680 { 00681 m_ptr = m_alloc.reallocate(m_ptr, m_size, newSize, true); 00682 memset_z(m_ptr+m_size, 0, (newSize-m_size)*sizeof(T)); 00683 m_size = newSize; 00684 } 00685 } 00686 00687 //! \brief Change size and preserve contents 00688 //! \param newSize the new size of the memory block 00689 //! \details Old content is preserved. If the memory block grows in size, then 00690 //! all content is uninitialized. 00691 //! \details Internally, this SecBlock calls reallocate(). 00692 //! \note reallocate() is called if the size increases. If the size does not 00693 //! increase, then Grow does not take action. If the size must change, 00694 //! then use resize(). 00695 //! \sa New(), CleanNew(), Grow(), CleanGrow(), resize() 00696 void resize(size_type newSize) 00697 { 00698 m_ptr = m_alloc.reallocate(m_ptr, m_size, newSize, true); 00699 m_size = newSize; 00700 } 00701 00702 //! \brief Swap contents with another SecBlock 00703 //! \param b the other SecBlock 00704 //! \details Internally, std::swap() is called on m_alloc, m_size and m_ptr. 00705 void swap(SecBlock<T, A> &b) 00706 { 00707 // Swap must occur on the allocator in case its FixedSize that spilled into the heap. 00708 std::swap(m_alloc, b.m_alloc); 00709 std::swap(m_size, b.m_size); 00710 std::swap(m_ptr, b.m_ptr); 00711 } 00712 00713 // protected: 00714 A m_alloc; 00715 size_type m_size; 00716 T *m_ptr; 00717 }; 00718 00719 #ifdef CRYPTOPP_DOXYGEN_PROCESSING 00720 //! \class SecByteBlock 00721 //! \brief SecByteBlock is a SecBlock<byte> typedef. 00722 class SecByteBlock : public SecBlock<byte> {}; 00723 //! \class SecWordBlock 00724 //! \brief SecWordBlock is a SecBlock<word> typedef. 00725 class SecWordBlock : public SecBlock<word> {}; 00726 //! \class AlignedSecByteBlock 00727 //! \brief AlignedSecByteBlock is a SecBlock<byte, AllocatorWithCleanup<byte, true> > typedef. 00728 class AlignedSecByteBlock SecBlock<byte, AllocatorWithCleanup<byte, true> > {}; 00729 #else 00730 typedef SecBlock<byte> SecByteBlock; 00731 typedef SecBlock<word> SecWordBlock; 00732 typedef SecBlock<byte, AllocatorWithCleanup<byte, true> > AlignedSecByteBlock; 00733 #endif 00734 00735 // No need for move semantics on derived class *if* the class does not add any 00736 // data members; see http://stackoverflow.com/q/31755703, and Rule of {0|3|5}. 00737 00738 //! \class FixedSizeSecBlock 00739 //! \brief Fixed size stack-based SecBlock 00740 //! \tparam T class or type 00741 //! \tparam S fixed-size of the stack-based memory block 00742 //! \tparam A AllocatorBase derived class for allocation and cleanup 00743 template <class T, unsigned int S, class A = FixedSizeAllocatorWithCleanup<T, S> > 00744 class FixedSizeSecBlock : public SecBlock<T, A> 00745 { 00746 public: 00747 //! \brief Construct a FixedSizeSecBlock 00748 explicit FixedSizeSecBlock() : SecBlock<T, A>(S) {} 00749 }; 00750 00751 //! \class FixedSizeAlignedSecBlock 00752 //! \brief Fixed size stack-based SecBlock with 16-byte alignment 00753 //! \tparam T class or type 00754 //! \tparam S fixed-size of the stack-based memory block 00755 //! \tparam A AllocatorBase derived class for allocation and cleanup 00756 template <class T, unsigned int S, bool T_Align16 = true> 00757 class FixedSizeAlignedSecBlock : public FixedSizeSecBlock<T, S, FixedSizeAllocatorWithCleanup<T, S, NullAllocator<T>, T_Align16> > 00758 { 00759 }; 00760 00761 //! \class SecBlockWithHint 00762 //! \brief Stack-based SecBlock that grows into the heap 00763 //! \tparam T class or type 00764 //! \tparam S fixed-size of the stack-based memory block 00765 //! \tparam A AllocatorBase derived class for allocation and cleanup 00766 template <class T, unsigned int S, class A = FixedSizeAllocatorWithCleanup<T, S, AllocatorWithCleanup<T> > > 00767 class SecBlockWithHint : public SecBlock<T, A> 00768 { 00769 public: 00770 //! construct a SecBlockWithHint with a count of elements 00771 explicit SecBlockWithHint(size_t size) : SecBlock<T, A>(size) {} 00772 }; 00773 00774 template<class T, bool A, class U, bool B> 00775 inline bool operator==(const CryptoPP::AllocatorWithCleanup<T, A>&, const CryptoPP::AllocatorWithCleanup<U, B>&) {return (true);} 00776 template<class T, bool A, class U, bool B> 00777 inline bool operator!=(const CryptoPP::AllocatorWithCleanup<T, A>&, const CryptoPP::AllocatorWithCleanup<U, B>&) {return (false);} 00778 00779 NAMESPACE_END 00780 00781 NAMESPACE_BEGIN(std) 00782 template <class T, class A> 00783 inline void swap(CryptoPP::SecBlock<T, A> &a, CryptoPP::SecBlock<T, A> &b) 00784 { 00785 a.swap(b); 00786 } 00787 00788 #if defined(_STLP_DONT_SUPPORT_REBIND_MEMBER_TEMPLATE) || (defined(_STLPORT_VERSION) && !defined(_STLP_MEMBER_TEMPLATE_CLASSES)) 00789 // working for STLport 5.1.3 and MSVC 6 SP5 00790 template <class _Tp1, class _Tp2> 00791 inline CryptoPP::AllocatorWithCleanup<_Tp2>& 00792 __stl_alloc_rebind(CryptoPP::AllocatorWithCleanup<_Tp1>& __a, const _Tp2*) 00793 { 00794 return (CryptoPP::AllocatorWithCleanup<_Tp2>&)(__a); 00795 } 00796 #endif 00797 00798 NAMESPACE_END 00799 00800 #if CRYPTOPP_MSC_VERSION 00801 # pragma warning(pop) 00802 #endif 00803 00804 #endif