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