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