Crypto++  5.6.3
Free C++ class library of cryptographic schemes
secblock.h
Go to the documentation of this file.
1 // secblock.h - written and placed in the public domain by Wei Dai
2 
3 //! \file secblock.h
4 //! \brief Classes and functions for secure memory allocations.
5 
6 #ifndef CRYPTOPP_SECBLOCK_H
7 #define CRYPTOPP_SECBLOCK_H
8 
9 #include "config.h"
10 #include "stdcpp.h"
11 #include "misc.h"
12 
13 #if CRYPTOPP_MSC_VERSION
14 # pragma warning(push)
15 # pragma warning(disable: 4700 6386)
16 #endif
17 
18 NAMESPACE_BEGIN(CryptoPP)
19 
20 // ************** secure memory allocation ***************
21 
22 //! \class AllocatorBase
23 //! \brief Base class for all allocators used by SecBlock
24 //! \tparam T the class or type
25 template<class T>
27 {
28 public:
29  typedef T value_type;
30  typedef size_t size_type;
31 #ifdef CRYPTOPP_MSVCRT6
32  typedef ptrdiff_t difference_type;
33 #else
34  typedef std::ptrdiff_t difference_type;
35 #endif
36  typedef T * pointer;
37  typedef const T * const_pointer;
38  typedef T & reference;
39  typedef const T & const_reference;
40 
41  pointer address(reference r) const {return (&r);}
42  const_pointer address(const_reference r) const {return (&r); }
43  void construct(pointer p, const T& val) {new (p) T(val);}
44  void destroy(pointer p) {CRYPTOPP_UNUSED(p); p->~T();}
45 
46  //! \brief Returns the maximum number of elements the allocator can provide
47  //! \returns the maximum number of elements the allocator can provide
48  //! \details Internally, preprocessor macros are used rather than std::numeric_limits
49  //! because the latter is \a not a \a constexpr. Some compilers, like Clang, do not
50  //! optimize it well under all circumstances. Compilers like GCC, ICC and MSVC appear
51  //! to optimize it well in either form.
52  size_type max_size() const {return (SIZE_MAX/sizeof(T));}
53 
54 #if defined(CRYPTOPP_CXX11_VARIADIC_TEMPLATES) || defined(CRYPTOPP_DOXYGEN_PROCESSING)
55 
56  //! \brief Constructs a new U using variadic arguments
57  //! \tparam U the type to be forwarded
58  //! \tparam Args the arguments to be forwarded
59  //! \param ptr pointer to type U
60  //! \param args variadic arguments
61  //! \details This is a C++11 feature. It is available when CRYPTOPP_CXX11_VARIADIC_TEMPLATES
62  //! is defined. The define is controlled by compiler versions detected in config.h.
63  template<typename U, typename... Args>
64  void construct(U* ptr, Args&&... args) {::new ((void*)ptr) U(std::forward<Args>(args)...);}
65 
66  //! \brief Destroys an U constructed with variadic arguments
67  //! \tparam U the type to be forwarded
68  //! \details This is a C++11 feature. It is available when CRYPTOPP_CXX11_VARIADIC_TEMPLATES
69  //! is defined. The define is controlled by compiler versions detected in config.h.
70  template<typename U>
71  void destroy(U* ptr) {if(ptr) ptr->~U();}
72 
73 #endif
74 
75 protected:
76 
77  //! \brief Verifies the allocator can satisfy a request based on size
78  //! \param size the number of elements
79  //! \throws InvalidArgument
80  //! \details CheckSize verifies the number of elements requested is valid.
81  //! \details If size is greater than max_size(), then InvalidArgument is thrown.
82  //! The library throws InvalidArgument if the size is too large to satisfy.
83  //! \details Internally, preprocessor macros are used rather than std::numeric_limits
84  //! because the latter is \a not a \a constexpr. Some compilers, like Clang, do not
85  //! optimize it well under all circumstances. Compilers like GCC, ICC and MSVC appear
86  //! to optimize it well in either form.
87  //! \note size is the count of elements, and not the number of bytes
88  static void CheckSize(size_t size)
89  {
90  // C++ throws std::bad_alloc (C++03) or std::bad_array_new_length (C++11) here.
91  if (size > (SIZE_MAX/sizeof(T)))
92  throw InvalidArgument("AllocatorBase: requested size would cause integer overflow");
93  }
94 };
95 
96 #define CRYPTOPP_INHERIT_ALLOCATOR_TYPES \
97 typedef typename AllocatorBase<T>::value_type value_type;\
98 typedef typename AllocatorBase<T>::size_type size_type;\
99 typedef typename AllocatorBase<T>::difference_type difference_type;\
100 typedef typename AllocatorBase<T>::pointer pointer;\
101 typedef typename AllocatorBase<T>::const_pointer const_pointer;\
102 typedef typename AllocatorBase<T>::reference reference;\
103 typedef typename AllocatorBase<T>::const_reference const_reference;
104 
105 //! \brief Reallocation function
106 //! \tparam T the class or type
107 //! \tparam A the class or type's allocator
108 //! \param alloc the allocator
109 //! \param oldPtr the previous allocation
110 //! \param oldSize the size of the previous allocation
111 //! \param newSize the new, requested size
112 //! \param preserve flag that indicates if the old allocation should be preserved
113 //! \note oldSize and newSize are the count of elements, and not the
114 //! number of bytes.
115 template <class T, class A>
116 typename A::pointer StandardReallocate(A& alloc, T *oldPtr, typename A::size_type oldSize, typename A::size_type newSize, bool preserve)
117 {
118  assert((oldPtr && oldSize) || !(oldPtr || oldSize));
119  if (oldSize == newSize)
120  return oldPtr;
121 
122  if (preserve)
123  {
124  typename A::pointer newPointer = alloc.allocate(newSize, NULL);
125  const size_t copySize = STDMIN(oldSize, newSize) * sizeof(T);
126 
127  if (oldPtr && newPointer) {memcpy_s(newPointer, copySize, oldPtr, copySize);}
128  alloc.deallocate(oldPtr, oldSize);
129  return newPointer;
130  }
131  else
132  {
133  alloc.deallocate(oldPtr, oldSize);
134  return alloc.allocate(newSize, NULL);
135  }
136 }
137 
138 //! \class AllocatorWithCleanup
139 //! \brief Allocates a block of memory with cleanup
140 //! \tparam T class or type
141 //! \tparam T_Align16 boolean that determines whether allocations should be aligned on 16-byte boundaries
142 //! \details If T_Align16 is true, then AllocatorWithCleanup calls AlignedAllocate()
143 //! for memory allocations. If T_Align16 is false, then AllocatorWithCleanup() calls
144 //! UnalignedAllocate() for memory allocations.
145 //! \details Template parameter T_Align16 is effectively controlled by cryptlib.h and mirrors
146 //! CRYPTOPP_BOOL_ALIGN16. CRYPTOPP_BOOL_ALIGN16 is often used as the template parameter.
147 template <class T, bool T_Align16 = false>
149 {
150 public:
151  CRYPTOPP_INHERIT_ALLOCATOR_TYPES
152 
153  //! \brief Allocates a block of memory
154  //! \param ptr the size of the allocation
155  //! \param size the size of the allocation
156  //! \returns a memory block
157  //! \throws InvalidArgument
158  //! \details allocate() first checks the size of the request. If it is non-0
159  //! and less than max_size(), then an attempt is made to fulfill the request using either
160  //! AlignedAllocate() or UnalignedAllocate().
161  //! \details AlignedAllocate() is used if T_Align16 is true.
162  //! UnalignedAllocate() used if T_Align16 is false.
163  //! \details This is the C++ *Placement New* operator. ptr is not used, and the function
164  //! asserts in Debug builds if ptr is non-NULL.
165  //! \sa CallNewHandler() for the methods used to recover from a failed
166  //! allocation attempt.
167  //! \note size is the count of elements, and not the number of bytes
168  pointer allocate(size_type size, const void *ptr = NULL)
169  {
170  CRYPTOPP_UNUSED(ptr); assert(ptr == NULL);
171  this->CheckSize(size);
172  if (size == 0)
173  return NULL;
174 
175 #if CRYPTOPP_BOOL_ALIGN16
176  // TODO: should this need the test 'size*sizeof(T) >= 16'?
177  if (T_Align16 && size*sizeof(T) >= 16)
178  return (pointer)AlignedAllocate(size*sizeof(T));
179 #endif
180 
181  return (pointer)UnalignedAllocate(size*sizeof(T));
182  }
183 
184  //! \brief Deallocates a block of memory
185  //! \param ptr the size of the allocation
186  //! \param size the size of the allocation
187  //! \details Internally, SecureWipeArray() is called before deallocating the memory.
188  //! Once the memory block is wiped or zeroized, AlignedDeallocate() or
189  //! UnalignedDeallocate() is called.
190  //! \details AlignedDeallocate() is used if T_Align16 is true.
191  //! UnalignedDeallocate() used if T_Align16 is false.
192  void deallocate(void *ptr, size_type size)
193  {
194  assert((ptr && size) || !(ptr || size));
195  SecureWipeArray((pointer)ptr, size);
196 
197 #if CRYPTOPP_BOOL_ALIGN16
198  if (T_Align16 && size*sizeof(T) >= 16)
199  return AlignedDeallocate(ptr);
200 #endif
201 
202  UnalignedDeallocate(ptr);
203  }
204 
205  //! \brief Reallocates a block of memory
206  //! \param oldPtr the previous allocation
207  //! \param oldSize the size of the previous allocation
208  //! \param newSize the new, requested size
209  //! \param preserve flag that indicates if the old allocation should be preserved
210  //! \returns pointer to the new memory block
211  //! \details Internally, reallocate() calls StandardReallocate().
212  //! \details If preserve is true, then index 0 is used to begin copying the
213  //! old memory block to the new one. If the block grows, then the old array
214  //! is copied in its entirety. If the block shrinks, then only newSize
215  //! elements are copied from the old block to the new one.
216  //! \note oldSize and newSize are the count of elements, and not the
217  //! number of bytes.
218  pointer reallocate(T *oldPtr, size_type oldSize, size_type newSize, bool preserve)
219  {
220  assert((oldPtr && oldSize) || !(oldPtr || oldSize));
221  return StandardReallocate(*this, oldPtr, oldSize, newSize, preserve);
222  }
223 
224  // VS.NET STL enforces the policy of "All STL-compliant allocators have to provide a
225  // template class member called rebind".
226  template <class U> struct rebind { typedef AllocatorWithCleanup<U, T_Align16> other; };
227 #if _MSC_VER >= 1500
229  template <class U, bool A> AllocatorWithCleanup(const AllocatorWithCleanup<U, A> &) {}
230 #endif
231 };
232 
233 CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup<byte>;
234 CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup<word16>;
235 CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup<word32>;
236 CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup<word64>;
237 #if CRYPTOPP_BOOL_X86
238 CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup<word, true>; // for Integer
239 #endif
240 
241 //! \class NullAllocator
242 //! \brief NULL allocator
243 //! \tparam T class or type
244 //! \details A NullAllocator is useful for fixed-size, stack based allocations
245 //! (i.e., static arrays used by FixedSizeAllocatorWithCleanup).
246 //! \details A NullAllocator always returns 0 for max_size(), and always returns
247 //! NULL for allocation requests. Though the allocator does not allocate at
248 //! runtime, it does perform a secure wipe or zeroization during cleanup.
249 template <class T>
250 class NullAllocator : public AllocatorBase<T>
251 {
252 public:
253  CRYPTOPP_INHERIT_ALLOCATOR_TYPES
254 
255  // TODO: should this return NULL or throw bad_alloc? Non-Windows C++ standard
256  // libraries always throw. And late mode Windows throws. Early model Windows
257  // (circa VC++ 6.0) returned NULL.
258  pointer allocate(size_type n, const void* unused = NULL)
259  {
260  CRYPTOPP_UNUSED(n); CRYPTOPP_UNUSED(unused);
261  assert(false); return NULL;
262  }
263 
264  void deallocate(void *p, size_type n)
265  {
266  CRYPTOPP_UNUSED(p); CRYPTOPP_UNUSED(n);
267  assert(false);
268  }
269 
270  size_type max_size() const {return 0;}
271 };
272 
273 //! \class FixedSizeAllocatorWithCleanup
274 //! \brief Static secure memory block with cleanup
275 //! \tparam T class or type
276 //! \tparam S fixed-size of the stack-based memory block
277 //! \tparam A AllocatorBase derived class for allocation and cleanup
278 //! \details FixedSizeAllocatorWithCleanup provides a fixed-size, stack-
279 //! based allocation at compile time. The class can grow its memory
280 //! block at runtime if a suitable allocator is available. If size
281 //! grows beyond S and a suitable allocator is available, then the
282 //! statically allocated array is obsoleted.
283 //! \note This allocator can't be used with standard collections because
284 //! they require that all objects of the same allocator type are equivalent.
285 template <class T, size_t S, class A = NullAllocator<T>, bool T_Align16 = false>
287 {
288 public:
289  CRYPTOPP_INHERIT_ALLOCATOR_TYPES
290 
291  //! \brief Constructs a FixedSizeAllocatorWithCleanup
292  FixedSizeAllocatorWithCleanup() : m_allocated(false) {}
293 
294  //! \brief Allocates a block of memory
295  //! \param size size of the memory block
296  //! \details FixedSizeAllocatorWithCleanup provides a fixed-size, stack-
297  //! based allocation at compile time. If size is less than or equal to
298  //! S, then a pointer to the static array is returned.
299  //! \details The class can grow its memory block at runtime if a suitable
300  //! allocator is available. If size grows beyond S and a suitable
301  //! allocator is available, then the statically allocated array is
302  //! obsoleted. If a suitable allocator is \a not available, as with a
303  //! NullAllocator, then the function returns NULL and a runtime error
304  //! eventually occurs.
305  //! \note size is the count of elements, and not the number of bytes.
306  //! \sa reallocate(), SecBlockWithHint
307  pointer allocate(size_type size)
308  {
309  assert(IsAlignedOn(m_array, 8));
310 
311  if (size <= S && !m_allocated)
312  {
313  m_allocated = true;
314  return GetAlignedArray();
315  }
316  else
317  return m_fallbackAllocator.allocate(size);
318  }
319 
320  //! \brief Allocates a block of memory
321  //! \param size size of the memory block
322  //! \param hint an unused hint
323  //! \details FixedSizeAllocatorWithCleanup provides a fixed-size, stack-
324  //! based allocation at compile time. If size is less than or equal to
325  //! S, then a pointer to the static array is returned.
326  //! \details The class can grow its memory block at runtime if a suitable
327  //! allocator is available. If size grows beyond S and a suitable
328  //! allocator is available, then the statically allocated array is
329  //! obsoleted. If a suitable allocator is \a not available, as with a
330  //! NullAllocator, then the function returns NULL and a runtime error
331  //! eventually occurs.
332  //! \note size is the count of elements, and not the number of bytes.
333  //! \sa reallocate(), SecBlockWithHint
334  pointer allocate(size_type size, const void *hint)
335  {
336  if (size <= S && !m_allocated)
337  {
338  m_allocated = true;
339  return GetAlignedArray();
340  }
341  else
342  return m_fallbackAllocator.allocate(size, hint);
343  }
344 
345  //! \brief Deallocates a block of memory
346  //! \param ptr a pointer to the memory block to deallocate
347  //! \param size size of the memory block
348  //! \details The memory block is wiped or zeroized before deallocation.
349  //! If the statically allocated memory block is active, then no
350  //! additional actions are taken after the wipe.
351  //! \details If a dynamic memory block is active, then the pointer and
352  //! size are passed to the allocator for deallocation.
353  void deallocate(void *ptr, size_type size)
354  {
355  if (ptr == GetAlignedArray())
356  {
357  assert(size <= S);
358  assert(m_allocated);
359  m_allocated = false;
360  SecureWipeArray((pointer)ptr, size);
361  }
362  else
363  m_fallbackAllocator.deallocate(ptr, size);
364  }
365 
366  //! \brief Reallocates a block of memory
367  //! \param oldPtr the previous allocation
368  //! \param oldSize the size of the previous allocation
369  //! \param newSize the new, requested size
370  //! \param preserve flag that indicates if the old allocation should be preserved
371  //! \returns pointer to the new memory block
372  //! \details FixedSizeAllocatorWithCleanup provides a fixed-size, stack-
373  //! based allocation at compile time. If size is less than or equal to
374  //! S, then a pointer to the static array is returned.
375  //! \details The class can grow its memory block at runtime if a suitable
376  //! allocator is available. If size grows beyond S and a suitable
377  //! allocator is available, then the statically allocated array is
378  //! obsoleted. If a suitable allocator is \a not available, as with a
379  //! NullAllocator, then the function returns NULL and a runtime error
380  //! eventually occurs.
381  //! \note size is the count of elements, and not the number of bytes.
382  //! \sa reallocate(), SecBlockWithHint
383  pointer reallocate(pointer oldPtr, size_type oldSize, size_type newSize, bool preserve)
384  {
385  if (oldPtr == GetAlignedArray() && newSize <= S)
386  {
387  assert(oldSize <= S);
388  if (oldSize > newSize)
389  SecureWipeArray(oldPtr+newSize, oldSize-newSize);
390  return oldPtr;
391  }
392 
393  pointer newPointer = allocate(newSize, NULL);
394  if (preserve && newSize)
395  {
396  const size_t copySize = STDMIN(oldSize, newSize);
397  memcpy_s(newPointer, copySize, oldPtr, copySize);
398  }
399  deallocate(oldPtr, oldSize);
400  return newPointer;
401  }
402 
403  size_type max_size() const {return STDMAX(m_fallbackAllocator.max_size(), S);}
404 
405 private:
406 #ifdef __BORLANDC__
407  T* GetAlignedArray() {return m_array;}
408  T m_array[S];
409 #else
410  T* GetAlignedArray() {return (CRYPTOPP_BOOL_ALIGN16 && T_Align16) ? (T*)(((byte *)m_array) + (0-(size_t)m_array)%16) : m_array;}
411  CRYPTOPP_ALIGN_DATA(8) T m_array[(CRYPTOPP_BOOL_ALIGN16 && T_Align16) ? S+8/sizeof(T) : S];
412 #endif
413  A m_fallbackAllocator;
414  bool m_allocated;
415 };
416 
417 //! \class SecBlock
418 //! \brief Secure memory block with allocator and cleanup
419 //! \tparam T a class or type
420 //! \tparam A AllocatorWithCleanup derived class for allocation and cleanup
421 template <class T, class A = AllocatorWithCleanup<T> >
422 class SecBlock
423 {
424 public:
425  typedef typename A::value_type value_type;
426  typedef typename A::pointer iterator;
427  typedef typename A::const_pointer const_iterator;
428  typedef typename A::size_type size_type;
429 
430  //! \brief Construct a SecBlock with space for size elements.
431  //! \param size the number of elements in the allocation
432  //! \throws std::bad_alloc
433  //! \details The elements are not initialized.
434  //! \note size is the count of elements, and not the number of bytes
435  explicit SecBlock(size_type size=0)
436  : m_size(size), m_ptr(m_alloc.allocate(size, NULL)) { }
437 
438  //! \brief Copy construct a SecBlock from another SecBlock
439  //! \param t the other SecBlock
440  //! \throws std::bad_alloc
442  : m_size(t.m_size), m_ptr(m_alloc.allocate(t.m_size, NULL)) {
443  assert((!t.m_ptr && !m_size) || (t.m_ptr && m_size));
444  if (t.m_ptr) {memcpy_s(m_ptr, m_size*sizeof(T), t.m_ptr, t.m_size*sizeof(T));}
445  }
446 
447  //! \brief Construct a SecBlock from an array of elements.
448  //! \param ptr a pointer to an array of T
449  //! \param len the number of elements in the memory block
450  //! \throws std::bad_alloc
451  //! \details If <tt>ptr!=NULL</tt> and <tt>len!=0</tt>, then the block is initialized from the pointer ptr.
452  //! If <tt>ptr==NULL</tt> and <tt>len!=0</tt>, then the block is initialized to 0.
453  //! Otherwise, the block is empty and uninitialized.
454  //! \note size is the count of elements, and not the number of bytes
455  SecBlock(const T *ptr, size_type len)
456  : m_size(len), m_ptr(m_alloc.allocate(len, NULL)) {
457  assert((!m_ptr && !m_size) || (m_ptr && m_size));
458  if (ptr && m_ptr)
459  memcpy_s(m_ptr, m_size*sizeof(T), ptr, len*sizeof(T));
460  else if (m_size)
461  memset(m_ptr, 0, m_size*sizeof(T));
462  }
463 
464  ~SecBlock()
465  {m_alloc.deallocate(m_ptr, m_size);}
466 
467 #ifdef __BORLANDC__
468  operator T *() const
469  {return (T*)m_ptr;}
470 #else
471  operator const void *() const
472  {return m_ptr;}
473  operator void *()
474  {return m_ptr;}
475 
476  operator const T *() const
477  {return m_ptr;}
478  operator T *()
479  {return m_ptr;}
480 #endif
481 
482  //! \brief Provides an iterator pointing to the first element in the memory block
483  //! \returns iterator pointing to the first element in the memory block
484  iterator begin()
485  {return m_ptr;}
486  //! \brief Provides a constant iterator pointing to the first element in the memory block
487  //! \returns constant iterator pointing to the first element in the memory block
488  const_iterator begin() const
489  {return m_ptr;}
490  //! \brief Provides an iterator pointing beyond the last element in the memory block
491  //! \returns iterator pointing beyond the last element in the memory block
492  iterator end()
493  {return m_ptr+m_size;}
494  //! \brief Provides a constant iterator pointing beyond the last element in the memory block
495  //! \returns constant iterator pointing beyond the last element in the memory block
496  const_iterator end() const
497  {return m_ptr+m_size;}
498 
499  //! \brief Provides a pointer to the first element in the memory block
500  //! \returns pointer to the first element in the memory block
501  typename A::pointer data() {return m_ptr;}
502  //! \brief Provides a pointer to the first element in the memory block
503  //! \returns constant pointer to the first element in the memory block
504  typename A::const_pointer data() const {return m_ptr;}
505 
506  //! \brief Provides the count of elements in the SecBlock
507  //! \returns number of elements in the memory block
508  //! \note the return value is the count of elements, and not the number of bytes
509  size_type size() const {return m_size;}
510  //! \brief Determines if the SecBlock is empty
511  //! \returns true if number of elements in the memory block is 0, false otherwise
512  bool empty() const {return m_size == 0;}
513 
514  //! \brief Provides a byte pointer to the first element in the memory block
515  //! \returns byte pointer to the first element in the memory block
516  byte * BytePtr() {return (byte *)m_ptr;}
517  //! \brief Return a byte pointer to the first element in the memory block
518  //! \returns constant byte pointer to the first element in the memory block
519  const byte * BytePtr() const {return (const byte *)m_ptr;}
520  //! \brief Provides the number of bytes in the SecBlock
521  //! \return the number of bytes in the memory block
522  //! \note the return value is the number of bytes, and not count of elements.
523  size_type SizeInBytes() const {return m_size*sizeof(T);}
524 
525  //! \brief Set contents and size from an array
526  //! \param ptr a pointer to an array of T
527  //! \param len the number of elements in the memory block
528  //! \details If the memory block is reduced in size, then the unused area is set to 0.
529  void Assign(const T *ptr, size_type len)
530  {
531  New(len);
532  if (m_ptr && ptr && len)
533  {memcpy_s(m_ptr, m_size*sizeof(T), ptr, len*sizeof(T));}
534  }
535 
536  //! \brief Copy contents from another SecBlock
537  //! \param t the other SecBlock
538  //! \details Assign checks for self assignment.
539  //! \details If the memory block is reduced in size, then the unused area is set to 0.
540  void Assign(const SecBlock<T, A> &t)
541  {
542  if (this != &t)
543  {
544  New(t.m_size);
545  if (m_ptr && t.m_ptr && t.m_size)
546  {memcpy_s(m_ptr, m_size*sizeof(T), t, t.m_size*sizeof(T));}
547  }
548  }
549 
550  //! \brief Assign contents from another SecBlock
551  //! \param t the other SecBlock
552  //! \details Internally, operator=() calls Assign().
553  //! \details If the memory block is reduced in size, then the unused area is set to 0.
555  {
556  // Assign guards for self-assignment
557  Assign(t);
558  return *this;
559  }
560 
561  //! \brief Append contents from another SecBlock
562  //! \param t the other SecBlock
563  //! \details Internally, this SecBlock calls Grow and then copies the new content.
564  //! \details If the memory block is reduced in size, then the unused area is set to 0.
566  {
567  assert((!t.m_ptr && !t.m_size) || (t.m_ptr && t.m_ptr.m_size));
568 
569  if(t.size)
570  {
571  size_type oldSize = m_size;
572  Grow(m_size+t.m_size);
573 
574  if (m_ptr && t.m_ptr)
575  {memcpy_s(m_ptr+oldSize, (m_size-oldSize)*sizeof(T), t.m_ptr, t.m_size*sizeof(T));}
576  }
577  return *this;
578  }
579 
580  //! \brief Concatenate contents from another SecBlock
581  //! \param t the other SecBlock
582  //! \returns a newly constructed SecBlock that is a conacentation of this and t
583  //! \details Internally, a temporary SecBlock is created and the content from this
584  //! SecBlock and the other SecBlock are concatenated. The temporary
585  //! SecBlock is returned to the caller.
587  {
588  assert((!m_ptr && !m_size) || (m_ptr && m_size));
589  assert((!t.m_ptr && !t.m_size) || (t.m_ptr && t.m_ptr.m_size));
590  if(!t.size) return SecBlock(*this);
591 
592  SecBlock<T, A> result(m_size+t.m_size);
593  memcpy_s(result.m_ptr, result.m_size*sizeof(T), m_ptr, m_size*sizeof(T));
594  memcpy_s(result.m_ptr+m_size, (t.m_size-m_size)*sizeof(T), t.m_ptr, t.m_size*sizeof(T));
595  return result;
596  }
597 
598  //! \brief Bitwise compare two SecBlocks
599  //! \param t the other SecBlock
600  //! \returns true if the size and bits are equal, false otherwise
601  //! \details Uses a constant time compare if the arrays are equal size. The constant time
602  //! compare is VerifyBufsEqual() found in misc.h.
603  //! \sa operator!=()
604  bool operator==(const SecBlock<T, A> &t) const
605  {
606  return m_size == t.m_size && VerifyBufsEqual(m_ptr, t.m_ptr, m_size*sizeof(T));
607  }
608 
609  //! \brief Bitwise compare two SecBlocks
610  //! \param t the other SecBlock
611  //! \returns true if the size and bits are equal, false otherwise
612  //! \details Uses a constant time compare if the arrays are equal size. The constant time
613  //! compare is VerifyBufsEqual() found in misc.h.
614  //! \details Internally, operator!=() returns the inverse of operator==().
615  //! \sa operator==()
616  bool operator!=(const SecBlock<T, A> &t) const
617  {
618  return !operator==(t);
619  }
620 
621  //! \brief Change size without preserving contents
622  //! \param newSize the new size of the memory block
623  //! \details Old content is \a not preserved. If the memory block is reduced in size,
624  //! then the unused content is set to 0. If the memory block grows in size, then
625  //! all content is uninitialized.
626  //! \details Internally, this SecBlock calls reallocate().
627  //! \sa New(), CleanNew(), Grow(), CleanGrow(), resize()
628  void New(size_type newSize)
629  {
630  m_ptr = m_alloc.reallocate(m_ptr, m_size, newSize, false);
631  m_size = newSize;
632  }
633 
634  //! \brief Change size without preserving contents
635  //! \param newSize the new size of the memory block
636  //! \details Old content is not preserved. If the memory block is reduced in size,
637  //! then the unused content is set to 0. Existing and new content is set to 0.
638  //! \details Internally, this SecBlock calls reallocate().
639  //! \sa New(), CleanNew(), Grow(), CleanGrow(), resize()
640  void CleanNew(size_type newSize)
641  {
642  New(newSize);
643  if (m_ptr) {memset_z(m_ptr, 0, m_size*sizeof(T));}
644  }
645 
646  //! \brief Change size and preserve contents
647  //! \param newSize the new size of the memory block
648  //! \details Old content is preserved. If the memory block grows in size, then
649  //! all content is uninitialized.
650  //! \details Internally, this SecBlock calls reallocate().
651  //! \note reallocate() is called if the size increases. If the size does not
652  //! increase, then Grow does not take action. If the size must change,
653  //! then use resize().
654  //! \sa New(), CleanNew(), Grow(), CleanGrow(), resize()
655  void Grow(size_type newSize)
656  {
657  if (newSize > m_size)
658  {
659  m_ptr = m_alloc.reallocate(m_ptr, m_size, newSize, true);
660  m_size = newSize;
661  }
662  }
663 
664  //! \brief Change size and preserve contents
665  //! \param newSize the new size of the memory block
666  //! \details Old content is preserved. If the memory block is reduced in size,
667  //! then the unused content is set to 0. If the memory block grows in size,
668  //! then the new content is uninitialized.
669  //! \details Internally, this SecBlock calls reallocate().
670  //! \note reallocate() is called if the size increases. If the size does not
671  //! increase, then Grow does not take action. If the size must change,
672  //! then use resize().
673  //! \sa New(), CleanNew(), Grow(), CleanGrow(), resize()
674  void CleanGrow(size_type newSize)
675  {
676  if (newSize > m_size)
677  {
678  m_ptr = m_alloc.reallocate(m_ptr, m_size, newSize, true);
679  memset_z(m_ptr+m_size, 0, (newSize-m_size)*sizeof(T));
680  m_size = newSize;
681  }
682  }
683 
684  //! \brief Change size and preserve contents
685  //! \param newSize the new size of the memory block
686  //! \details Old content is preserved. If the memory block grows in size, then
687  //! all content is uninitialized.
688  //! \details Internally, this SecBlock calls reallocate().
689  //! \note reallocate() is called if the size increases. If the size does not
690  //! increase, then Grow does not take action. If the size must change,
691  //! then use resize().
692  //! \sa New(), CleanNew(), Grow(), CleanGrow(), resize()
693  void resize(size_type newSize)
694  {
695  m_ptr = m_alloc.reallocate(m_ptr, m_size, newSize, true);
696  m_size = newSize;
697  }
698 
699  //! \brief Swap contents with another SecBlock
700  //! \param b the other SecBlock
701  //! \details Internally, std::swap() is called on m_alloc, m_size and m_ptr.
703  {
704  // Swap must occur on the allocator in case its FixedSize that spilled into the heap.
705  std::swap(m_alloc, b.m_alloc);
706  std::swap(m_size, b.m_size);
707  std::swap(m_ptr, b.m_ptr);
708  }
709 
710 // protected:
711  A m_alloc;
712  size_type m_size;
713  T *m_ptr;
714 };
715 
716 #ifdef CRYPTOPP_DOXYGEN_PROCESSING
717 //! \class SecByteBlock
718 //! \brief SecByteBlock is a SecBlock<byte> typedef.
719 class SecByteBlock : public SecBlock<byte> {};
720 //! \class SecWordBlock
721 //! \brief SecWordBlock is a SecBlock<word> typedef.
722 class SecWordBlock : public SecBlock<word> {};
723 //! \class AlignedSecByteBlock
724 //! \brief AlignedSecByteBlock is a SecBlock<byte, AllocatorWithCleanup<byte, true> > typedef.
725 class AlignedSecByteBlock SecBlock<byte, AllocatorWithCleanup<byte, true> > {};
726 #else
730 #endif
731 
732 // No need for move semantics on derived class *if* the class does not add any
733 // data members; see http://stackoverflow.com/q/31755703, and Rule of {0|3|5}.
734 
735 //! \class FixedSizeSecBlock
736 //! \brief Fixed size stack-based SecBlock
737 //! \tparam T class or type
738 //! \tparam S fixed-size of the stack-based memory block
739 //! \tparam A AllocatorBase derived class for allocation and cleanup
740 template <class T, unsigned int S, class A = FixedSizeAllocatorWithCleanup<T, S> >
741 class FixedSizeSecBlock : public SecBlock<T, A>
742 {
743 public:
744  //! \brief Construct a FixedSizeSecBlock
745  explicit FixedSizeSecBlock() : SecBlock<T, A>(S) {}
746 };
747 
748 //! \class FixedSizeAlignedSecBlock
749 //! \brief Fixed size stack-based SecBlock with 16-byte alignment
750 //! \tparam T class or type
751 //! \tparam S fixed-size of the stack-based memory block
752 //! \tparam A AllocatorBase derived class for allocation and cleanup
753 template <class T, unsigned int S, bool T_Align16 = true>
754 class FixedSizeAlignedSecBlock : public FixedSizeSecBlock<T, S, FixedSizeAllocatorWithCleanup<T, S, NullAllocator<T>, T_Align16> >
755 {
756 };
757 
758 //! \class SecBlockWithHint
759 //! \brief Stack-based SecBlock that grows into the heap
760 //! \tparam T class or type
761 //! \tparam S fixed-size of the stack-based memory block
762 //! \tparam A AllocatorBase derived class for allocation and cleanup
763 template <class T, unsigned int S, class A = FixedSizeAllocatorWithCleanup<T, S, AllocatorWithCleanup<T> > >
764 class SecBlockWithHint : public SecBlock<T, A>
765 {
766 public:
767  //! construct a SecBlockWithHint with a count of elements
768  explicit SecBlockWithHint(size_t size) : SecBlock<T, A>(size) {}
769 };
770 
771 template<class T, bool A, class U, bool B>
772 inline bool operator==(const CryptoPP::AllocatorWithCleanup<T, A>&, const CryptoPP::AllocatorWithCleanup<U, B>&) {return (true);}
773 template<class T, bool A, class U, bool B>
774 inline bool operator!=(const CryptoPP::AllocatorWithCleanup<T, A>&, const CryptoPP::AllocatorWithCleanup<U, B>&) {return (false);}
775 
776 NAMESPACE_END
777 
778 NAMESPACE_BEGIN(std)
779 template <class T, class A>
780 inline void swap(CryptoPP::SecBlock<T, A> &a, CryptoPP::SecBlock<T, A> &b)
781 {
782  a.swap(b);
783 }
784 
785 #if defined(_STLP_DONT_SUPPORT_REBIND_MEMBER_TEMPLATE) || (defined(_STLPORT_VERSION) && !defined(_STLP_MEMBER_TEMPLATE_CLASSES))
786 // working for STLport 5.1.3 and MSVC 6 SP5
787 template <class _Tp1, class _Tp2>
788 inline CryptoPP::AllocatorWithCleanup<_Tp2>&
789 __stl_alloc_rebind(CryptoPP::AllocatorWithCleanup<_Tp1>& __a, const _Tp2*)
790 {
791  return (CryptoPP::AllocatorWithCleanup<_Tp2>&)(__a);
792 }
793 #endif
794 
795 NAMESPACE_END
796 
797 #if CRYPTOPP_MSC_VERSION
798 # pragma warning(pop)
799 #endif
800 
801 #endif
iterator end()
Provides an iterator pointing beyond the last element in the memory block.
Definition: secblock.h:492
An invalid argument was detected.
Definition: cryptlib.h:166
Base class for all allocators used by SecBlock.
Definition: secblock.h:26
void swap(SecBlock< T, A > &b)
Swap contents with another SecBlock.
Definition: secblock.h:702
Stack-based SecBlock that grows into the heap.
Definition: secblock.h:764
void destroy(U *ptr)
Destroys an U constructed with variadic arguments.
Definition: secblock.h:71
Utility functions for the Crypto++ library.
void construct(U *ptr, Args &&...args)
Constructs a new U using variadic arguments.
Definition: secblock.h:64
void AlignedDeallocate(void *ptr)
Frees a buffer allocated with AlignedAllocate.
FixedSizeSecBlock()
Construct a FixedSizeSecBlock.
Definition: secblock.h:745
void CleanNew(size_type newSize)
Change size without preserving contents.
Definition: secblock.h:640
bool operator!=(const SecBlock< T, A > &t) const
Bitwise compare two SecBlocks.
Definition: secblock.h:616
A::const_pointer data() const
Provides a pointer to the first element in the memory block.
Definition: secblock.h:504
bool empty() const
Determines if the SecBlock is empty.
Definition: secblock.h:512
SecBlock< T, A > & operator=(const SecBlock< T, A > &t)
Assign contents from another SecBlock.
Definition: secblock.h:554
void resize(size_type newSize)
Change size and preserve contents.
Definition: secblock.h:693
SecBlock< T, A > & operator+=(const SecBlock< T, A > &t)
Append contents from another SecBlock.
Definition: secblock.h:565
void CleanGrow(size_type newSize)
Change size and preserve contents.
Definition: secblock.h:674
void Assign(const SecBlock< T, A > &t)
Copy contents from another SecBlock.
Definition: secblock.h:540
SecBlock< T, A > operator+(const SecBlock< T, A > &t)
Concatenate contents from another SecBlock.
Definition: secblock.h:586
SecBlock(size_type size=0)
Construct a SecBlock with space for size elements.
Definition: secblock.h:435
const_iterator begin() const
Provides a constant iterator pointing to the first element in the memory block.
Definition: secblock.h:488
Secure memory block with allocator and cleanup.
Definition: secblock.h:422
void memcpy_s(void *dest, size_t sizeInBytes, const void *src, size_t count)
Bounds checking replacement for memcpy()
Definition: misc.h:296
size_type size() const
Provides the count of elements in the SecBlock.
Definition: secblock.h:509
Library configuration file.
STL namespace.
pointer allocate(size_type size, const void *hint)
Allocates a block of memory.
Definition: secblock.h:334
void New(size_type newSize)
Change size without preserving contents.
Definition: secblock.h:628
SecByteBlock is a SecBlock<byte> typedef.
Definition: secblock.h:719
pointer reallocate(T *oldPtr, size_type oldSize, size_type newSize, bool preserve)
Reallocates a block of memory.
Definition: secblock.h:218
size_type max_size() const
Returns the maximum number of elements the allocator can provide.
Definition: secblock.h:52
Static secure memory block with cleanup.
Definition: secblock.h:286
Allocates a block of memory with cleanup.
Definition: secblock.h:148
void deallocate(void *ptr, size_type size)
Deallocates a block of memory.
Definition: secblock.h:353
void SecureWipeArray(T *buf, size_t n)
Sets each element of an array to 0.
Definition: misc.h:1038
bool IsAlignedOn(const void *ptr, unsigned int alignment)
Determines whether ptr is aligned to a minimum value.
Definition: misc.h:801
const_iterator end() const
Provides a constant iterator pointing beyond the last element in the memory block.
Definition: secblock.h:496
void * UnalignedAllocate(size_t size)
Allocates a buffer.
Definition: misc.cpp:192
A::pointer data()
Provides a pointer to the first element in the memory block.
Definition: secblock.h:501
void Assign(const T *ptr, size_type len)
Set contents and size from an array.
Definition: secblock.h:529
pointer reallocate(pointer oldPtr, size_type oldSize, size_type newSize, bool preserve)
Reallocates a block of memory.
Definition: secblock.h:383
Fixed size stack-based SecBlock with 16-byte alignment.
Definition: secblock.h:754
AlignedSecByteBlock is a SecBlock<byte, AllocatorWithCleanup<byte, true> > typedef.
pointer allocate(size_type size, const void *ptr=NULL)
Allocates a block of memory.
Definition: secblock.h:168
Fixed size stack-based SecBlock.
Definition: secblock.h:741
SecBlock(const SecBlock< T, A > &t)
Copy construct a SecBlock from another SecBlock.
Definition: secblock.h:441
void * memset_z(void *ptr, int value, size_t num)
Memory block initializer and eraser that attempts to survive optimizations.
Definition: misc.h:370
const T & STDMIN(const T &a, const T &b)
Replacement function for std::min.
Definition: misc.h:386
void deallocate(void *ptr, size_type size)
Deallocates a block of memory.
Definition: secblock.h:192
iterator begin()
Provides an iterator pointing to the first element in the memory block.
Definition: secblock.h:484
const byte * BytePtr() const
Return a byte pointer to the first element in the memory block.
Definition: secblock.h:519
NULL allocator.
Definition: secblock.h:250
SecBlockWithHint(size_t size)
construct a SecBlockWithHint with a count of elements
Definition: secblock.h:768
A::pointer StandardReallocate(A &alloc, T *oldPtr, typename A::size_type oldSize, typename A::size_type newSize, bool preserve)
Reallocation function.
Definition: secblock.h:116
bool VerifyBufsEqual(const byte *buf1, const byte *buf2, size_t count)
Performs a near constant-time comparison of two equally sized buffers.
Definition: misc.cpp:93
SecBlock(const T *ptr, size_type len)
Construct a SecBlock from an array of elements.
Definition: secblock.h:455
pointer allocate(size_type size)
Allocates a block of memory.
Definition: secblock.h:307
const T & STDMAX(const T &a, const T &b)
Replacement function for std::max.
Definition: misc.h:396
void Grow(size_type newSize)
Change size and preserve contents.
Definition: secblock.h:655
Crypto++ library namespace.
bool operator==(const SecBlock< T, A > &t) const
Bitwise compare two SecBlocks.
Definition: secblock.h:604
size_type SizeInBytes() const
Provides the number of bytes in the SecBlock.
Definition: secblock.h:523
FixedSizeAllocatorWithCleanup()
Constructs a FixedSizeAllocatorWithCleanup.
Definition: secblock.h:292
void UnalignedDeallocate(void *ptr)
Frees a buffer allocated with UnalignedAllocate.
Definition: misc.cpp:200
SecWordBlock is a SecBlock<word> typedef.
Definition: secblock.h:722
void * AlignedAllocate(size_t size)
Allocates a buffer on 16-byte boundary.
#define SIZE_MAX
The maximum value of a machine word.
Definition: misc.h:70
byte * BytePtr()
Provides a byte pointer to the first element in the memory block.
Definition: secblock.h:516