From b21162cf8e06f40baa1f58be6a8c17435cebc34d Mon Sep 17 00:00:00 2001 From: weidai Date: Fri, 4 Oct 2002 17:31:41 +0000 Subject: Initial revision git-svn-id: svn://svn.code.sf.net/p/cryptopp/code/trunk/c5@2 57ff6487-cd31-0410-9ec3-f628ee90f5f0 --- secblock.h | 376 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 376 insertions(+) create mode 100644 secblock.h (limited to 'secblock.h') diff --git a/secblock.h b/secblock.h new file mode 100644 index 0000000..31997b6 --- /dev/null +++ b/secblock.h @@ -0,0 +1,376 @@ +// 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); +} + +NAMESPACE_END + +#endif -- cgit v1.2.1