summaryrefslogtreecommitdiff
path: root/external/crypto++-5.6.3/secblock.h
diff options
context:
space:
mode:
Diffstat (limited to 'external/crypto++-5.6.3/secblock.h')
-rw-r--r--external/crypto++-5.6.3/secblock.h804
1 files changed, 804 insertions, 0 deletions
diff --git a/external/crypto++-5.6.3/secblock.h b/external/crypto++-5.6.3/secblock.h
new file mode 100644
index 0000000..ef8cab1
--- /dev/null
+++ b/external/crypto++-5.6.3/secblock.h
@@ -0,0 +1,804 @@
+// secblock.h - written and placed in the public domain by Wei Dai
+
+//! \file secblock.h
+//! \brief Classes and functions for secure memory allocations.
+
+#ifndef CRYPTOPP_SECBLOCK_H
+#define CRYPTOPP_SECBLOCK_H
+
+#include "config.h"
+#include "stdcpp.h"
+#include "misc.h"
+
+#if CRYPTOPP_MSC_VERSION
+# pragma warning(push)
+# pragma warning(disable: 4700)
+# if (CRYPTOPP_MSC_VERSION >= 1400)
+# pragma warning(disable: 6386)
+# endif
+#endif
+
+NAMESPACE_BEGIN(CryptoPP)
+
+// ************** secure memory allocation ***************
+
+//! \class AllocatorBase
+//! \brief Base class for all allocators used by SecBlock
+//! \tparam T the class or type
+template<class T>
+class AllocatorBase
+{
+public:
+ typedef T value_type;
+ typedef size_t size_type;
+#ifdef CRYPTOPP_MSVCRT6
+ 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) {CRYPTOPP_UNUSED(p); p->~T();}
+
+ //! \brief Returns the maximum number of elements the allocator can provide
+ //! \returns the maximum number of elements the allocator can provide
+ //! \details Internally, preprocessor macros are used rather than std::numeric_limits
+ //! because the latter is \a not a \a constexpr. Some compilers, like Clang, do not
+ //! optimize it well under all circumstances. Compilers like GCC, ICC and MSVC appear
+ //! to optimize it well in either form.
+ size_type max_size() const {return (SIZE_MAX/sizeof(T));}
+
+#if defined(CRYPTOPP_CXX11_VARIADIC_TEMPLATES) || defined(CRYPTOPP_DOXYGEN_PROCESSING)
+
+ //! \brief Constructs a new U using variadic arguments
+ //! \tparam U the type to be forwarded
+ //! \tparam Args the arguments to be forwarded
+ //! \param ptr pointer to type U
+ //! \param args variadic arguments
+ //! \details This is a C++11 feature. It is available when CRYPTOPP_CXX11_VARIADIC_TEMPLATES
+ //! is defined. The define is controlled by compiler versions detected in config.h.
+ template<typename U, typename... Args>
+ void construct(U* ptr, Args&&... args) {::new ((void*)ptr) U(std::forward<Args>(args)...);}
+
+ //! \brief Destroys an U constructed with variadic arguments
+ //! \tparam U the type to be forwarded
+ //! \details This is a C++11 feature. It is available when CRYPTOPP_CXX11_VARIADIC_TEMPLATES
+ //! is defined. The define is controlled by compiler versions detected in config.h.
+ template<typename U>
+ void destroy(U* ptr) {if(ptr) ptr->~U();}
+
+#endif
+
+protected:
+
+ //! \brief Verifies the allocator can satisfy a request based on size
+ //! \param size the number of elements
+ //! \throws InvalidArgument
+ //! \details CheckSize verifies the number of elements requested is valid.
+ //! \details If size is greater than max_size(), then InvalidArgument is thrown.
+ //! The library throws InvalidArgument if the size is too large to satisfy.
+ //! \details Internally, preprocessor macros are used rather than std::numeric_limits
+ //! because the latter is \a not a \a constexpr. Some compilers, like Clang, do not
+ //! optimize it well under all circumstances. Compilers like GCC, ICC and MSVC appear
+ //! to optimize it well in either form.
+ //! \note size is the count of elements, and not the number of bytes
+ static void CheckSize(size_t size)
+ {
+ // C++ throws std::bad_alloc (C++03) or std::bad_array_new_length (C++11) here.
+ if (size > (SIZE_MAX/sizeof(T)))
+ throw InvalidArgument("AllocatorBase: requested size would cause integer overflow");
+ }
+};
+
+#define CRYPTOPP_INHERIT_ALLOCATOR_TYPES \
+typedef typename AllocatorBase<T>::value_type value_type;\
+typedef typename AllocatorBase<T>::size_type size_type;\
+typedef typename AllocatorBase<T>::difference_type difference_type;\
+typedef typename AllocatorBase<T>::pointer pointer;\
+typedef typename AllocatorBase<T>::const_pointer const_pointer;\
+typedef typename AllocatorBase<T>::reference reference;\
+typedef typename AllocatorBase<T>::const_reference const_reference;
+
+//! \brief Reallocation function
+//! \tparam T the class or type
+//! \tparam A the class or type's allocator
+//! \param alloc the allocator
+//! \param oldPtr the previous allocation
+//! \param oldSize the size of the previous allocation
+//! \param newSize the new, requested size
+//! \param preserve flag that indicates if the old allocation should be preserved
+//! \note oldSize and newSize are the count of elements, and not the
+//! number of bytes.
+template <class T, class A>
+typename A::pointer StandardReallocate(A& alloc, T *oldPtr, typename A::size_type oldSize, typename A::size_type newSize, bool preserve)
+{
+ assert((oldPtr && oldSize) || !(oldPtr || oldSize));
+ if (oldSize == newSize)
+ return oldPtr;
+
+ if (preserve)
+ {
+ typename A::pointer newPointer = alloc.allocate(newSize, NULL);
+ const size_t copySize = STDMIN(oldSize, newSize) * sizeof(T);
+
+ if (oldPtr && newPointer) {memcpy_s(newPointer, copySize, oldPtr, copySize);}
+ alloc.deallocate(oldPtr, oldSize);
+ return newPointer;
+ }
+ else
+ {
+ alloc.deallocate(oldPtr, oldSize);
+ return alloc.allocate(newSize, NULL);
+ }
+}
+
+//! \class AllocatorWithCleanup
+//! \brief Allocates a block of memory with cleanup
+//! \tparam T class or type
+//! \tparam T_Align16 boolean that determines whether allocations should be aligned on 16-byte boundaries
+//! \details If T_Align16 is true, then AllocatorWithCleanup calls AlignedAllocate()
+//! for memory allocations. If T_Align16 is false, then AllocatorWithCleanup() calls
+//! UnalignedAllocate() for memory allocations.
+//! \details Template parameter T_Align16 is effectively controlled by cryptlib.h and mirrors
+//! CRYPTOPP_BOOL_ALIGN16. CRYPTOPP_BOOL_ALIGN16 is often used as the template parameter.
+template <class T, bool T_Align16 = false>
+class AllocatorWithCleanup : public AllocatorBase<T>
+{
+public:
+ CRYPTOPP_INHERIT_ALLOCATOR_TYPES
+
+ //! \brief Allocates a block of memory
+ //! \param ptr the size of the allocation
+ //! \param size the size of the allocation
+ //! \returns a memory block
+ //! \throws InvalidArgument
+ //! \details allocate() first checks the size of the request. If it is non-0
+ //! and less than max_size(), then an attempt is made to fulfill the request using either
+ //! AlignedAllocate() or UnalignedAllocate().
+ //! \details AlignedAllocate() is used if T_Align16 is true.
+ //! UnalignedAllocate() used if T_Align16 is false.
+ //! \details This is the C++ *Placement New* operator. ptr is not used, and the function
+ //! asserts in Debug builds if ptr is non-NULL.
+ //! \sa CallNewHandler() for the methods used to recover from a failed
+ //! allocation attempt.
+ //! \note size is the count of elements, and not the number of bytes
+ pointer allocate(size_type size, const void *ptr = NULL)
+ {
+ CRYPTOPP_UNUSED(ptr); assert(ptr == NULL);
+ this->CheckSize(size);
+ if (size == 0)
+ return NULL;
+
+#if CRYPTOPP_BOOL_ALIGN16
+ // TODO: should this need the test 'size*sizeof(T) >= 16'?
+ if (T_Align16 && size*sizeof(T) >= 16)
+ return (pointer)AlignedAllocate(size*sizeof(T));
+#endif
+
+ return (pointer)UnalignedAllocate(size*sizeof(T));
+ }
+
+ //! \brief Deallocates a block of memory
+ //! \param ptr the size of the allocation
+ //! \param size the size of the allocation
+ //! \details Internally, SecureWipeArray() is called before deallocating the memory.
+ //! Once the memory block is wiped or zeroized, AlignedDeallocate() or
+ //! UnalignedDeallocate() is called.
+ //! \details AlignedDeallocate() is used if T_Align16 is true.
+ //! UnalignedDeallocate() used if T_Align16 is false.
+ void deallocate(void *ptr, size_type size)
+ {
+ assert((ptr && size) || !(ptr || size));
+ SecureWipeArray((pointer)ptr, size);
+
+#if CRYPTOPP_BOOL_ALIGN16
+ if (T_Align16 && size*sizeof(T) >= 16)
+ return AlignedDeallocate(ptr);
+#endif
+
+ UnalignedDeallocate(ptr);
+ }
+
+ //! \brief Reallocates a block of memory
+ //! \param oldPtr the previous allocation
+ //! \param oldSize the size of the previous allocation
+ //! \param newSize the new, requested size
+ //! \param preserve flag that indicates if the old allocation should be preserved
+ //! \returns pointer to the new memory block
+ //! \details Internally, reallocate() calls StandardReallocate().
+ //! \details If preserve is true, then index 0 is used to begin copying the
+ //! old memory block to the new one. If the block grows, then the old array
+ //! is copied in its entirety. If the block shrinks, then only newSize
+ //! elements are copied from the old block to the new one.
+ //! \note oldSize and newSize are the count of elements, and not the
+ //! number of bytes.
+ pointer reallocate(T *oldPtr, size_type oldSize, size_type newSize, bool preserve)
+ {
+ assert((oldPtr && oldSize) || !(oldPtr || oldSize));
+ return StandardReallocate(*this, oldPtr, oldSize, newSize, preserve);
+ }
+
+ // VS.NET STL enforces the policy of "All STL-compliant allocators have to provide a
+ // template class member called rebind".
+ template <class U> struct rebind { typedef AllocatorWithCleanup<U, T_Align16> other; };
+#if _MSC_VER >= 1500
+ AllocatorWithCleanup() {}
+ template <class U, bool A> AllocatorWithCleanup(const AllocatorWithCleanup<U, A> &) {}
+#endif
+};
+
+CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup<byte>;
+CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup<word16>;
+CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup<word32>;
+CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup<word64>;
+#if CRYPTOPP_BOOL_X86
+CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup<word, true>; // for Integer
+#endif
+
+//! \class NullAllocator
+//! \brief NULL allocator
+//! \tparam T class or type
+//! \details A NullAllocator is useful for fixed-size, stack based allocations
+//! (i.e., static arrays used by FixedSizeAllocatorWithCleanup).
+//! \details A NullAllocator always returns 0 for max_size(), and always returns
+//! NULL for allocation requests. Though the allocator does not allocate at
+//! runtime, it does perform a secure wipe or zeroization during cleanup.
+template <class T>
+class NullAllocator : public AllocatorBase<T>
+{
+public:
+ CRYPTOPP_INHERIT_ALLOCATOR_TYPES
+
+ // TODO: should this return NULL or throw bad_alloc? Non-Windows C++ standard
+ // libraries always throw. And late mode Windows throws. Early model Windows
+ // (circa VC++ 6.0) returned NULL.
+ pointer allocate(size_type n, const void* unused = NULL)
+ {
+ CRYPTOPP_UNUSED(n); CRYPTOPP_UNUSED(unused);
+ assert(false); return NULL;
+ }
+
+ void deallocate(void *p, size_type n)
+ {
+ CRYPTOPP_UNUSED(p); CRYPTOPP_UNUSED(n);
+ assert(false);
+ }
+
+ size_type max_size() const {return 0;}
+};
+
+//! \class FixedSizeAllocatorWithCleanup
+//! \brief Static secure memory block with cleanup
+//! \tparam T class or type
+//! \tparam S fixed-size of the stack-based memory block
+//! \tparam A AllocatorBase derived class for allocation and cleanup
+//! \details FixedSizeAllocatorWithCleanup provides a fixed-size, stack-
+//! based allocation at compile time. The class can grow its memory
+//! block at runtime if a suitable allocator is available. If size
+//! grows beyond S and a suitable allocator is available, then the
+//! statically allocated array is obsoleted.
+//! \note This allocator can't be used with standard collections because
+//! they require that all objects of the same allocator type are equivalent.
+template <class T, size_t S, class A = NullAllocator<T>, bool T_Align16 = false>
+class FixedSizeAllocatorWithCleanup : public AllocatorBase<T>
+{
+public:
+ CRYPTOPP_INHERIT_ALLOCATOR_TYPES
+
+ //! \brief Constructs a FixedSizeAllocatorWithCleanup
+ FixedSizeAllocatorWithCleanup() : m_allocated(false) {}
+
+ //! \brief Allocates a block of memory
+ //! \param size size of the memory block
+ //! \details FixedSizeAllocatorWithCleanup provides a fixed-size, stack-
+ //! based allocation at compile time. If size is less than or equal to
+ //! S, then a pointer to the static array is returned.
+ //! \details The class can grow its memory block at runtime if a suitable
+ //! allocator is available. If size grows beyond S and a suitable
+ //! allocator is available, then the statically allocated array is
+ //! obsoleted. If a suitable allocator is \a not available, as with a
+ //! NullAllocator, then the function returns NULL and a runtime error
+ //! eventually occurs.
+ //! \note size is the count of elements, and not the number of bytes.
+ //! \sa reallocate(), SecBlockWithHint
+ pointer allocate(size_type size)
+ {
+ assert(IsAlignedOn(m_array, 8));
+
+ if (size <= S && !m_allocated)
+ {
+ m_allocated = true;
+ return GetAlignedArray();
+ }
+ else
+ return m_fallbackAllocator.allocate(size);
+ }
+
+ //! \brief Allocates a block of memory
+ //! \param size size of the memory block
+ //! \param hint an unused hint
+ //! \details FixedSizeAllocatorWithCleanup provides a fixed-size, stack-
+ //! based allocation at compile time. If size is less than or equal to
+ //! S, then a pointer to the static array is returned.
+ //! \details The class can grow its memory block at runtime if a suitable
+ //! allocator is available. If size grows beyond S and a suitable
+ //! allocator is available, then the statically allocated array is
+ //! obsoleted. If a suitable allocator is \a not available, as with a
+ //! NullAllocator, then the function returns NULL and a runtime error
+ //! eventually occurs.
+ //! \note size is the count of elements, and not the number of bytes.
+ //! \sa reallocate(), SecBlockWithHint
+ pointer allocate(size_type size, const void *hint)
+ {
+ if (size <= S && !m_allocated)
+ {
+ m_allocated = true;
+ return GetAlignedArray();
+ }
+ else
+ return m_fallbackAllocator.allocate(size, hint);
+ }
+
+ //! \brief Deallocates a block of memory
+ //! \param ptr a pointer to the memory block to deallocate
+ //! \param size size of the memory block
+ //! \details The memory block is wiped or zeroized before deallocation.
+ //! If the statically allocated memory block is active, then no
+ //! additional actions are taken after the wipe.
+ //! \details If a dynamic memory block is active, then the pointer and
+ //! size are passed to the allocator for deallocation.
+ void deallocate(void *ptr, size_type size)
+ {
+ if (ptr == GetAlignedArray())
+ {
+ assert(size <= S);
+ assert(m_allocated);
+ m_allocated = false;
+ SecureWipeArray((pointer)ptr, size);
+ }
+ else
+ m_fallbackAllocator.deallocate(ptr, size);
+ }
+
+ //! \brief Reallocates a block of memory
+ //! \param oldPtr the previous allocation
+ //! \param oldSize the size of the previous allocation
+ //! \param newSize the new, requested size
+ //! \param preserve flag that indicates if the old allocation should be preserved
+ //! \returns pointer to the new memory block
+ //! \details FixedSizeAllocatorWithCleanup provides a fixed-size, stack-
+ //! based allocation at compile time. If size is less than or equal to
+ //! S, then a pointer to the static array is returned.
+ //! \details The class can grow its memory block at runtime if a suitable
+ //! allocator is available. If size grows beyond S and a suitable
+ //! allocator is available, then the statically allocated array is
+ //! obsoleted. If a suitable allocator is \a not available, as with a
+ //! NullAllocator, then the function returns NULL and a runtime error
+ //! eventually occurs.
+ //! \note size is the count of elements, and not the number of bytes.
+ //! \sa reallocate(), SecBlockWithHint
+ pointer reallocate(pointer oldPtr, size_type oldSize, size_type newSize, bool preserve)
+ {
+ if (oldPtr == GetAlignedArray() && newSize <= S)
+ {
+ assert(oldSize <= S);
+ if (oldSize > newSize)
+ SecureWipeArray(oldPtr+newSize, oldSize-newSize);
+ return oldPtr;
+ }
+
+ pointer newPointer = allocate(newSize, NULL);
+ if (preserve && newSize)
+ {
+ const size_t copySize = STDMIN(oldSize, newSize);
+ memcpy_s(newPointer, copySize, oldPtr, copySize);
+ }
+ deallocate(oldPtr, oldSize);
+ return newPointer;
+ }
+
+ size_type max_size() const {return STDMAX(m_fallbackAllocator.max_size(), S);}
+
+private:
+#ifdef __BORLANDC__
+ T* GetAlignedArray() {return m_array;}
+ T m_array[S];
+#else
+ T* GetAlignedArray() {return (CRYPTOPP_BOOL_ALIGN16 && T_Align16) ? (T*)(((byte *)m_array) + (0-(size_t)m_array)%16) : m_array;}
+ CRYPTOPP_ALIGN_DATA(8) T m_array[(CRYPTOPP_BOOL_ALIGN16 && T_Align16) ? S+8/sizeof(T) : S];
+#endif
+ A m_fallbackAllocator;
+ bool m_allocated;
+};
+
+//! \class SecBlock
+//! \brief Secure memory block with allocator and cleanup
+//! \tparam T a class or type
+//! \tparam A AllocatorWithCleanup derived class for allocation and cleanup
+template <class T, class A = AllocatorWithCleanup<T> >
+class SecBlock
+{
+public:
+ typedef typename A::value_type value_type;
+ typedef typename A::pointer iterator;
+ typedef typename A::const_pointer const_iterator;
+ typedef typename A::size_type size_type;
+
+ //! \brief Construct a SecBlock with space for size elements.
+ //! \param size the number of elements in the allocation
+ //! \throws std::bad_alloc
+ //! \details The elements are not initialized.
+ //! \note size is the count of elements, and not the number of bytes
+ explicit SecBlock(size_type size=0)
+ : m_size(size), m_ptr(m_alloc.allocate(size, NULL)) { }
+
+ //! \brief Copy construct a SecBlock from another SecBlock
+ //! \param t the other SecBlock
+ //! \throws std::bad_alloc
+ SecBlock(const SecBlock<T, A> &t)
+ : m_size(t.m_size), m_ptr(m_alloc.allocate(t.m_size, NULL)) {
+ assert((!t.m_ptr && !m_size) || (t.m_ptr && m_size));
+ if (t.m_ptr) {memcpy_s(m_ptr, m_size*sizeof(T), t.m_ptr, t.m_size*sizeof(T));}
+ }
+
+ //! \brief Construct a SecBlock from an array of elements.
+ //! \param ptr a pointer to an array of T
+ //! \param len the number of elements in the memory block
+ //! \throws std::bad_alloc
+ //! \details If <tt>ptr!=NULL</tt> and <tt>len!=0</tt>, then the block is initialized from the pointer ptr.
+ //! If <tt>ptr==NULL</tt> and <tt>len!=0</tt>, then the block is initialized to 0.
+ //! Otherwise, the block is empty and uninitialized.
+ //! \note size is the count of elements, and not the number of bytes
+ SecBlock(const T *ptr, size_type len)
+ : m_size(len), m_ptr(m_alloc.allocate(len, NULL)) {
+ assert((!m_ptr && !m_size) || (m_ptr && m_size));
+ if (ptr && m_ptr)
+ memcpy_s(m_ptr, m_size*sizeof(T), ptr, len*sizeof(T));
+ else if (m_size)
+ memset(m_ptr, 0, m_size*sizeof(T));
+ }
+
+ ~SecBlock()
+ {m_alloc.deallocate(m_ptr, m_size);}
+
+#ifdef __BORLANDC__
+ operator T *() const
+ {return (T*)m_ptr;}
+#else
+ operator const void *() const
+ {return m_ptr;}
+ operator void *()
+ {return m_ptr;}
+
+ operator const T *() const
+ {return m_ptr;}
+ operator T *()
+ {return m_ptr;}
+#endif
+
+ //! \brief Provides an iterator pointing to the first element in the memory block
+ //! \returns iterator pointing to the first element in the memory block
+ iterator begin()
+ {return m_ptr;}
+ //! \brief Provides a constant iterator pointing to the first element in the memory block
+ //! \returns constant iterator pointing to the first element in the memory block
+ const_iterator begin() const
+ {return m_ptr;}
+ //! \brief Provides an iterator pointing beyond the last element in the memory block
+ //! \returns iterator pointing beyond the last element in the memory block
+ iterator end()
+ {return m_ptr+m_size;}
+ //! \brief Provides a constant iterator pointing beyond the last element in the memory block
+ //! \returns constant iterator pointing beyond the last element in the memory block
+ const_iterator end() const
+ {return m_ptr+m_size;}
+
+ //! \brief Provides a pointer to the first element in the memory block
+ //! \returns pointer to the first element in the memory block
+ typename A::pointer data() {return m_ptr;}
+ //! \brief Provides a pointer to the first element in the memory block
+ //! \returns constant pointer to the first element in the memory block
+ typename A::const_pointer data() const {return m_ptr;}
+
+ //! \brief Provides the count of elements in the SecBlock
+ //! \returns number of elements in the memory block
+ //! \note the return value is the count of elements, and not the number of bytes
+ size_type size() const {return m_size;}
+ //! \brief Determines if the SecBlock is empty
+ //! \returns true if number of elements in the memory block is 0, false otherwise
+ bool empty() const {return m_size == 0;}
+
+ //! \brief Provides a byte pointer to the first element in the memory block
+ //! \returns byte pointer to the first element in the memory block
+ byte * BytePtr() {return (byte *)m_ptr;}
+ //! \brief Return a byte pointer to the first element in the memory block
+ //! \returns constant byte pointer to the first element in the memory block
+ const byte * BytePtr() const {return (const byte *)m_ptr;}
+ //! \brief Provides the number of bytes in the SecBlock
+ //! \return the number of bytes in the memory block
+ //! \note the return value is the number of bytes, and not count of elements.
+ size_type SizeInBytes() const {return m_size*sizeof(T);}
+
+ //! \brief Set contents and size from an array
+ //! \param ptr a pointer to an array of T
+ //! \param len the number of elements in the memory block
+ //! \details If the memory block is reduced in size, then the unused area is set to 0.
+ void Assign(const T *ptr, size_type len)
+ {
+ New(len);
+ if (m_ptr && ptr && len)
+ {memcpy_s(m_ptr, m_size*sizeof(T), ptr, len*sizeof(T));}
+ }
+
+ //! \brief Copy contents from another SecBlock
+ //! \param t the other SecBlock
+ //! \details Assign checks for self assignment.
+ //! \details If the memory block is reduced in size, then the unused area is set to 0.
+ void Assign(const SecBlock<T, A> &t)
+ {
+ if (this != &t)
+ {
+ New(t.m_size);
+ if (m_ptr && t.m_ptr && t.m_size)
+ {memcpy_s(m_ptr, m_size*sizeof(T), t, t.m_size*sizeof(T));}
+ }
+ }
+
+ //! \brief Assign contents from another SecBlock
+ //! \param t the other SecBlock
+ //! \details Internally, operator=() calls Assign().
+ //! \details If the memory block is reduced in size, then the unused area is set to 0.
+ SecBlock<T, A>& operator=(const SecBlock<T, A> &t)
+ {
+ // Assign guards for self-assignment
+ Assign(t);
+ return *this;
+ }
+
+ //! \brief Append contents from another SecBlock
+ //! \param t the other SecBlock
+ //! \details Internally, this SecBlock calls Grow and then copies the new content.
+ //! \details If the memory block is reduced in size, then the unused area is set to 0.
+ SecBlock<T, A>& operator+=(const SecBlock<T, A> &t)
+ {
+ assert((!t.m_ptr && !t.m_size) || (t.m_ptr && t.m_ptr.m_size));
+
+ if(t.size)
+ {
+ size_type oldSize = m_size;
+ Grow(m_size+t.m_size);
+
+ if (m_ptr && t.m_ptr)
+ {memcpy_s(m_ptr+oldSize, (m_size-oldSize)*sizeof(T), t.m_ptr, t.m_size*sizeof(T));}
+ }
+ return *this;
+ }
+
+ //! \brief Concatenate contents from another SecBlock
+ //! \param t the other SecBlock
+ //! \returns a newly constructed SecBlock that is a conacentation of this and t
+ //! \details Internally, a temporary SecBlock is created and the content from this
+ //! SecBlock and the other SecBlock are concatenated. The temporary
+ //! SecBlock is returned to the caller.
+ SecBlock<T, A> operator+(const SecBlock<T, A> &t)
+ {
+ assert((!m_ptr && !m_size) || (m_ptr && m_size));
+ assert((!t.m_ptr && !t.m_size) || (t.m_ptr && t.m_ptr.m_size));
+ if(!t.size) return SecBlock(*this);
+
+ SecBlock<T, A> result(m_size+t.m_size);
+ memcpy_s(result.m_ptr, result.m_size*sizeof(T), m_ptr, m_size*sizeof(T));
+ memcpy_s(result.m_ptr+m_size, (t.m_size-m_size)*sizeof(T), t.m_ptr, t.m_size*sizeof(T));
+ return result;
+ }
+
+ //! \brief Bitwise compare two SecBlocks
+ //! \param t the other SecBlock
+ //! \returns true if the size and bits are equal, false otherwise
+ //! \details Uses a constant time compare if the arrays are equal size. The constant time
+ //! compare is VerifyBufsEqual() found in misc.h.
+ //! \sa operator!=()
+ bool operator==(const SecBlock<T, A> &t) const
+ {
+ return m_size == t.m_size && VerifyBufsEqual(m_ptr, t.m_ptr, m_size*sizeof(T));
+ }
+
+ //! \brief Bitwise compare two SecBlocks
+ //! \param t the other SecBlock
+ //! \returns true if the size and bits are equal, false otherwise
+ //! \details Uses a constant time compare if the arrays are equal size. The constant time
+ //! compare is VerifyBufsEqual() found in misc.h.
+ //! \details Internally, operator!=() returns the inverse of operator==().
+ //! \sa operator==()
+ bool operator!=(const SecBlock<T, A> &t) const
+ {
+ return !operator==(t);
+ }
+
+ //! \brief Change size without preserving contents
+ //! \param newSize the new size of the memory block
+ //! \details Old content is \a not preserved. If the memory block is reduced in size,
+ //! then the unused content is set to 0. If the memory block grows in size, then
+ //! all content is uninitialized.
+ //! \details Internally, this SecBlock calls reallocate().
+ //! \sa New(), CleanNew(), Grow(), CleanGrow(), resize()
+ void New(size_type newSize)
+ {
+ m_ptr = m_alloc.reallocate(m_ptr, m_size, newSize, false);
+ m_size = newSize;
+ }
+
+ //! \brief Change size without preserving contents
+ //! \param newSize the new size of the memory block
+ //! \details Old content is not preserved. If the memory block is reduced in size,
+ //! then the unused content is set to 0. Existing and new content is set to 0.
+ //! \details Internally, this SecBlock calls reallocate().
+ //! \sa New(), CleanNew(), Grow(), CleanGrow(), resize()
+ void CleanNew(size_type newSize)
+ {
+ New(newSize);
+ if (m_ptr) {memset_z(m_ptr, 0, m_size*sizeof(T));}
+ }
+
+ //! \brief Change size and preserve contents
+ //! \param newSize the new size of the memory block
+ //! \details Old content is preserved. If the memory block grows in size, then
+ //! all content is uninitialized.
+ //! \details Internally, this SecBlock calls reallocate().
+ //! \note reallocate() is called if the size increases. If the size does not
+ //! increase, then Grow does not take action. If the size must change,
+ //! then use resize().
+ //! \sa New(), CleanNew(), Grow(), CleanGrow(), resize()
+ void Grow(size_type newSize)
+ {
+ if (newSize > m_size)
+ {
+ m_ptr = m_alloc.reallocate(m_ptr, m_size, newSize, true);
+ m_size = newSize;
+ }
+ }
+
+ //! \brief Change size and preserve contents
+ //! \param newSize the new size of the memory block
+ //! \details Old content is preserved. If the memory block is reduced in size,
+ //! then the unused content is set to 0. If the memory block grows in size,
+ //! then the new content is uninitialized.
+ //! \details Internally, this SecBlock calls reallocate().
+ //! \note reallocate() is called if the size increases. If the size does not
+ //! increase, then Grow does not take action. If the size must change,
+ //! then use resize().
+ //! \sa New(), CleanNew(), Grow(), CleanGrow(), resize()
+ void CleanGrow(size_type newSize)
+ {
+ if (newSize > m_size)
+ {
+ m_ptr = m_alloc.reallocate(m_ptr, m_size, newSize, true);
+ memset_z(m_ptr+m_size, 0, (newSize-m_size)*sizeof(T));
+ m_size = newSize;
+ }
+ }
+
+ //! \brief Change size and preserve contents
+ //! \param newSize the new size of the memory block
+ //! \details Old content is preserved. If the memory block grows in size, then
+ //! all content is uninitialized.
+ //! \details Internally, this SecBlock calls reallocate().
+ //! \note reallocate() is called if the size increases. If the size does not
+ //! increase, then Grow does not take action. If the size must change,
+ //! then use resize().
+ //! \sa New(), CleanNew(), Grow(), CleanGrow(), resize()
+ void resize(size_type newSize)
+ {
+ m_ptr = m_alloc.reallocate(m_ptr, m_size, newSize, true);
+ m_size = newSize;
+ }
+
+ //! \brief Swap contents with another SecBlock
+ //! \param b the other SecBlock
+ //! \details Internally, std::swap() is called on m_alloc, m_size and m_ptr.
+ void swap(SecBlock<T, A> &b)
+ {
+ // Swap must occur on the allocator in case its FixedSize that spilled into the heap.
+ std::swap(m_alloc, b.m_alloc);
+ std::swap(m_size, b.m_size);
+ std::swap(m_ptr, b.m_ptr);
+ }
+
+// protected:
+ A m_alloc;
+ size_type m_size;
+ T *m_ptr;
+};
+
+#ifdef CRYPTOPP_DOXYGEN_PROCESSING
+//! \class SecByteBlock
+//! \brief SecByteBlock is a SecBlock<byte> typedef.
+class SecByteBlock : public SecBlock<byte> {};
+//! \class SecWordBlock
+//! \brief SecWordBlock is a SecBlock<word> typedef.
+class SecWordBlock : public SecBlock<word> {};
+//! \class AlignedSecByteBlock
+//! \brief AlignedSecByteBlock is a SecBlock<byte, AllocatorWithCleanup<byte, true> > typedef.
+class AlignedSecByteBlock SecBlock<byte, AllocatorWithCleanup<byte, true> > {};
+#else
+typedef SecBlock<byte> SecByteBlock;
+typedef SecBlock<word> SecWordBlock;
+typedef SecBlock<byte, AllocatorWithCleanup<byte, true> > AlignedSecByteBlock;
+#endif
+
+// No need for move semantics on derived class *if* the class does not add any
+// data members; see http://stackoverflow.com/q/31755703, and Rule of {0|3|5}.
+
+//! \class FixedSizeSecBlock
+//! \brief Fixed size stack-based SecBlock
+//! \tparam T class or type
+//! \tparam S fixed-size of the stack-based memory block
+//! \tparam A AllocatorBase derived class for allocation and cleanup
+template <class T, unsigned int S, class A = FixedSizeAllocatorWithCleanup<T, S> >
+class FixedSizeSecBlock : public SecBlock<T, A>
+{
+public:
+ //! \brief Construct a FixedSizeSecBlock
+ explicit FixedSizeSecBlock() : SecBlock<T, A>(S) {}
+};
+
+//! \class FixedSizeAlignedSecBlock
+//! \brief Fixed size stack-based SecBlock with 16-byte alignment
+//! \tparam T class or type
+//! \tparam S fixed-size of the stack-based memory block
+//! \tparam A AllocatorBase derived class for allocation and cleanup
+template <class T, unsigned int S, bool T_Align16 = true>
+class FixedSizeAlignedSecBlock : public FixedSizeSecBlock<T, S, FixedSizeAllocatorWithCleanup<T, S, NullAllocator<T>, T_Align16> >
+{
+};
+
+//! \class SecBlockWithHint
+//! \brief Stack-based SecBlock that grows into the heap
+//! \tparam T class or type
+//! \tparam S fixed-size of the stack-based memory block
+//! \tparam A AllocatorBase derived class for allocation and cleanup
+template <class T, unsigned int S, class A = FixedSizeAllocatorWithCleanup<T, S, AllocatorWithCleanup<T> > >
+class SecBlockWithHint : public SecBlock<T, A>
+{
+public:
+ //! construct a SecBlockWithHint with a count of elements
+ explicit SecBlockWithHint(size_t size) : SecBlock<T, A>(size) {}
+};
+
+template<class T, bool A, class U, bool B>
+inline bool operator==(const CryptoPP::AllocatorWithCleanup<T, A>&, const CryptoPP::AllocatorWithCleanup<U, B>&) {return (true);}
+template<class T, bool A, class U, bool B>
+inline bool operator!=(const CryptoPP::AllocatorWithCleanup<T, A>&, const CryptoPP::AllocatorWithCleanup<U, B>&) {return (false);}
+
+NAMESPACE_END
+
+NAMESPACE_BEGIN(std)
+template <class T, class A>
+inline void swap(CryptoPP::SecBlock<T, A> &a, CryptoPP::SecBlock<T, A> &b)
+{
+ a.swap(b);
+}
+
+#if defined(_STLP_DONT_SUPPORT_REBIND_MEMBER_TEMPLATE) || (defined(_STLPORT_VERSION) && !defined(_STLP_MEMBER_TEMPLATE_CLASSES))
+// working for STLport 5.1.3 and MSVC 6 SP5
+template <class _Tp1, class _Tp2>
+inline CryptoPP::AllocatorWithCleanup<_Tp2>&
+__stl_alloc_rebind(CryptoPP::AllocatorWithCleanup<_Tp1>& __a, const _Tp2*)
+{
+ return (CryptoPP::AllocatorWithCleanup<_Tp2>&)(__a);
+}
+#endif
+
+NAMESPACE_END
+
+#if CRYPTOPP_MSC_VERSION
+# pragma warning(pop)
+#endif
+
+#endif