// secblock.h - written and placed in the public domain by Wei Dai #ifndef CRYPTOPP_SECBLOCK_H #define CRYPTOPP_SECBLOCK_H #include "config.h" #include "misc.h" #include // CodeWarrior doesn't have memory.h #include NAMESPACE_BEGIN(CryptoPP) // ************** secure memory allocation *************** template class AllocatorBase { public: typedef T value_type; typedef size_t size_type; #if (defined(_MSC_VER) && _MSC_VER < 1300) typedef ptrdiff_t difference_type; #else typedef std::ptrdiff_t difference_type; #endif typedef T * pointer; typedef const T * const_pointer; typedef T & reference; typedef const T & const_reference; pointer address(reference r) const {return (&r);} const_pointer address(const_reference r) const {return (&r); } void construct(pointer p, const T& val) {new (p) T(val);} void destroy(pointer p) {p->~T();} size_type max_size() const {return size_type(-1)/sizeof(T);} }; #define CRYPTOPP_INHERIT_ALLOCATOR_TYPES \ typedef typename AllocatorBase::value_type value_type;\ typedef typename AllocatorBase::size_type size_type;\ typedef typename AllocatorBase::difference_type difference_type;\ typedef typename AllocatorBase::pointer pointer;\ typedef typename AllocatorBase::const_pointer const_pointer;\ typedef typename AllocatorBase::reference reference;\ typedef typename AllocatorBase::const_reference const_reference; template typename A::pointer StandardReallocate(A& a, T *p, typename A::size_type oldSize, typename A::size_type newSize, bool preserve) { if (oldSize == newSize) return p; if (preserve) { typename A::pointer newPointer = a.allocate(newSize, NULL); memcpy(newPointer, p, sizeof(T)*STDMIN(oldSize, newSize)); a.deallocate(p, oldSize); return newPointer; } else { a.deallocate(p, oldSize); return a.allocate(newSize, NULL); } } template class AllocatorWithCleanup : public AllocatorBase { public: CRYPTOPP_INHERIT_ALLOCATOR_TYPES pointer allocate(size_type n, const void * = NULL) { if (n > 0) return new T[n]; else return NULL; } void deallocate(void *p, size_type n) { memset(p, 0, n*sizeof(T)); delete [] (T *)p; } pointer reallocate(T *p, size_type oldSize, size_type newSize, bool preserve) { return StandardReallocate(*this, p, oldSize, newSize, preserve); } // VS.NET STL enforces the policy of "All STL-compliant allocators have to provide a // template class member called rebind". template struct rebind { typedef AllocatorWithCleanup other; }; }; template class NullAllocator : public AllocatorBase { public: CRYPTOPP_INHERIT_ALLOCATOR_TYPES pointer allocate(size_type n, const void * = NULL) { assert(false); return NULL; } void deallocate(void *p, size_type n) { assert(false); } }; // this allocator can't be used with standard collections template > class FixedSizeAllocatorWithCleanup : public AllocatorBase { public: CRYPTOPP_INHERIT_ALLOCATOR_TYPES pointer allocate(size_type n) { if (n <= S) { assert(!m_allocated); #ifndef NDEBUG m_allocated = true; #endif return m_array; } else return m_fallbackAllocator.allocate(n); } pointer allocate(size_type n, const void *hint) { if (n <= S) { assert(!m_allocated); #ifndef NDEBUG m_allocated = true; #endif return m_array; } else return m_fallbackAllocator.allocate(n, hint); } void deallocate(void *p, size_type n) { if (n <= S) { assert(m_allocated); assert(p == m_array); #ifndef NDEBUG m_allocated = false; #endif memset(p, 0, n*sizeof(T)); } else m_fallbackAllocator.deallocate(p, n); } pointer reallocate(pointer p, size_type oldSize, size_type newSize, bool preserve) { if (oldSize <= S && newSize <= S) return p; return StandardReallocate(*this, p, oldSize, newSize, preserve); } size_type max_size() const {return m_fallbackAllocator.max_size();} private: A m_fallbackAllocator; T m_array[S]; #ifndef NDEBUG public: FixedSizeAllocatorWithCleanup() : m_allocated(false) {} bool m_allocated; #endif }; //! a block of memory allocated using A template > class SecBlock { public: explicit SecBlock(unsigned int size=0) : m_size(size) {m_ptr = m_alloc.allocate(size, NULL);} SecBlock(const SecBlock &t) : m_size(t.m_size) {m_ptr = m_alloc.allocate(m_size, NULL); memcpy(m_ptr, t.m_ptr, m_size*sizeof(T));} SecBlock(const T *t, unsigned int len) : m_size(len) { m_ptr = m_alloc.allocate(len, NULL); if (t == NULL) memset(m_ptr, 0, len*sizeof(T)); else memcpy(m_ptr, t, len*sizeof(T)); } ~SecBlock() {m_alloc.deallocate(m_ptr, m_size);} #if defined(__GNUC__) || defined(__BCPLUSPLUS__) operator const void *() const {return m_ptr;} operator void *() {return m_ptr;} #endif #if defined(__GNUC__) // reduce warnings operator const void *() {return m_ptr;} #endif operator const T *() const {return m_ptr;} operator T *() {return m_ptr;} #if defined(__GNUC__) // reduce warnings operator const T *() {return m_ptr;} #endif template T *operator +(I offset) {return m_ptr+offset;} template const T *operator +(I offset) const {return m_ptr+offset;} template T& operator[](I index) {assert(index >= 0 && (unsigned int)index < m_size); return m_ptr[index];} template const T& operator[](I index) const {assert(index >= 0 && (unsigned int)index < m_size); return m_ptr[index];} typedef typename A::pointer iterator; typedef typename A::const_pointer const_iterator; typedef typename A::size_type size_type; iterator begin() {return m_ptr;} const_iterator begin() const {return m_ptr;} iterator end() {return m_ptr+m_size;} const_iterator end() const {return m_ptr+m_size;} typename A::pointer data() {return m_ptr;} typename A::const_pointer data() const {return m_ptr;} size_type size() const {return m_size;} bool empty() const {return m_size == 0;} void Assign(const T *t, unsigned int len) { New(len); memcpy(m_ptr, t, len*sizeof(T)); } void Assign(const SecBlock &t) { New(t.m_size); memcpy(m_ptr, t.m_ptr, m_size*sizeof(T)); } SecBlock& operator=(const SecBlock &t) { Assign(t); return *this; } bool operator==(const SecBlock &t) const { return m_size == t.m_size && memcmp(m_ptr, t.m_ptr, m_size*sizeof(T)) == 0; } bool operator!=(const SecBlock &t) const { return !operator==(t); } void New(unsigned int newSize) { m_ptr = m_alloc.reallocate(m_ptr, m_size, newSize, false); m_size = newSize; } void CleanNew(unsigned int newSize) { New(newSize); memset(m_ptr, 0, m_size*sizeof(T)); } void Grow(unsigned int newSize) { if (newSize > m_size) { m_ptr = m_alloc.reallocate(m_ptr, m_size, newSize, true); m_size = newSize; } } void CleanGrow(unsigned int newSize) { if (newSize > m_size) { m_ptr = m_alloc.reallocate(m_ptr, m_size, newSize, true); memset(m_ptr+m_size, 0, (newSize-m_size)*sizeof(T)); m_size = newSize; } } void resize(unsigned int newSize) { m_ptr = m_alloc.reallocate(m_ptr, m_size, newSize, true); m_size = newSize; } void swap(SecBlock &b); //private: A m_alloc; unsigned int m_size; T *m_ptr; }; template void SecBlock::swap(SecBlock &b) { std::swap(m_alloc, b.m_alloc); std::swap(m_size, b.m_size); std::swap(m_ptr, b.m_ptr); } typedef SecBlock SecByteBlock; typedef SecBlock SecWordBlock; template > class FixedSizeSecBlock : public SecBlock { public: explicit FixedSizeSecBlock() : SecBlock(S) {} }; template > > class SecBlockWithHint : public SecBlock { public: explicit SecBlockWithHint(unsigned int size) : SecBlock(size) {} }; template inline bool operator==(const CryptoPP::AllocatorWithCleanup&, const CryptoPP::AllocatorWithCleanup&) {return (true);} template inline bool operator!=(const CryptoPP::AllocatorWithCleanup&, const CryptoPP::AllocatorWithCleanup&) {return (false);} NAMESPACE_END NAMESPACE_BEGIN(std) template inline void swap(CryptoPP::SecBlock &a, CryptoPP::SecBlock &b) { a.swap(b); } #if defined(_STLPORT_VERSION) && !defined(_STLP_MEMBER_TEMPLATE_CLASSES) template inline CryptoPP::AllocatorWithCleanup<_Tp2>& __stl_alloc_rebind(CryptoPP::AllocatorWithCleanup<_Tp1>& __a, const _Tp2*) { return (CryptoPP::AllocatorWithCleanup<_Tp2>&)(__a); } #endif NAMESPACE_END #endif