Crypto++  7.0
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: 4231 4275 4700)
16 # if (CRYPTOPP_MSC_VERSION >= 1400)
17 # pragma warning(disable: 6011 6386 28193)
18 # endif
19 #endif
20 
21 NAMESPACE_BEGIN(CryptoPP)
22 
23 // ************** secure memory allocation ***************
24 
25 /// \brief Base class for all allocators used by SecBlock
26 /// \tparam T the class or type
27 template<class T>
29 {
30 public:
31  typedef T value_type;
32  typedef size_t size_type;
33  typedef std::ptrdiff_t difference_type;
34  typedef T * pointer;
35  typedef const T * const_pointer;
36  typedef T & reference;
37  typedef const T & const_reference;
38 
39  pointer address(reference r) const {return (&r);}
40  const_pointer address(const_reference r) const {return (&r); }
41  void construct(pointer p, const T& val) {new (p) T(val);}
42  void destroy(pointer p) {CRYPTOPP_UNUSED(p); p->~T();}
43 
44  /// \brief Returns the maximum number of elements the allocator can provide
45  /// \details <tt>ELEMS_MAX</tt> is the maximum number of elements the
46  /// <tt>Allocator</tt> can provide. The value of <tt>ELEMS_MAX</tt> is
47  /// <tt>SIZE_MAX/sizeof(T)</tt>. <tt>std::numeric_limits</tt> was avoided
48  /// due to lack of <tt>constexpr</tt>-ness in C++03 and below.
49  /// \note In C++03 and below <tt>ELEMS_MAX</tt> is a static data member of type
50  /// <tt>size_type</tt>. In C++11 and above <tt>ELEMS_MAX</tt> is an <tt>enum</tt>
51  /// inheriting from <tt>size_type</tt>. In both cases <tt>ELEMS_MAX</tt> can be
52  /// used before objects are fully constructed, and it does not suffer the
53  /// limitations of class methods like <tt>max_size</tt>.
54  /// \sa <A HREF="http://github.com/weidai11/cryptopp/issues/346">Issue 346/CVE-2016-9939</A>
55  /// \since Crypto++ 6.0
56 #if defined(CRYPTOPP_DOXYGEN_PROCESSING)
57  static const size_type ELEMS_MAX = ...;
58 #elif defined(_MSC_VER) && (_MSC_VER <= 1400)
59  static const size_type ELEMS_MAX = (~(size_type)0)/sizeof(T);
60 #elif defined(CRYPTOPP_CXX11_ENUM)
61  enum : size_type {ELEMS_MAX = SIZE_MAX/sizeof(T)};
62 #else
63  static const size_type ELEMS_MAX = SIZE_MAX/sizeof(T);
64 #endif
65 
66  /// \brief Returns the maximum number of elements the allocator can provide
67  /// \returns the maximum number of elements the allocator can provide
68  /// \details Internally, preprocessor macros are used rather than std::numeric_limits
69  /// because the latter is not a constexpr. Some compilers, like Clang, do not
70  /// optimize it well under all circumstances. Compilers like GCC, ICC and MSVC appear
71  /// to optimize it well in either form.
72  CRYPTOPP_CONSTEXPR size_type max_size() const {return ELEMS_MAX;}
73 
74 #if defined(CRYPTOPP_CXX11_VARIADIC_TEMPLATES) || defined(CRYPTOPP_DOXYGEN_PROCESSING)
75 
76  /// \brief Constructs a new V using variadic arguments
77  /// \tparam V the type to be forwarded
78  /// \tparam Args the arguments to be forwarded
79  /// \param ptr pointer to type V
80  /// \param args variadic arguments
81  /// \details This is a C++11 feature. It is available when CRYPTOPP_CXX11_VARIADIC_TEMPLATES
82  /// is defined. The define is controlled by compiler versions detected in config.h.
83  template<typename V, typename... Args>
84  void construct(V* ptr, Args&&... args) {::new ((void*)ptr) V(std::forward<Args>(args)...);}
85 
86  /// \brief Destroys an V constructed with variadic arguments
87  /// \tparam V the type to be forwarded
88  /// \details This is a C++11 feature. It is available when CRYPTOPP_CXX11_VARIADIC_TEMPLATES
89  /// is defined. The define is controlled by compiler versions detected in config.h.
90  template<typename V>
91  void destroy(V* ptr) {if (ptr) ptr->~V();}
92 
93 #endif
94 
95 protected:
96 
97  /// \brief Verifies the allocator can satisfy a request based on size
98  /// \param size the size of the allocation, in elements
99  /// \throws InvalidArgument
100  /// \details CheckSize verifies the number of elements requested is valid.
101  /// \details If size is greater than max_size(), then InvalidArgument is thrown.
102  /// The library throws InvalidArgument if the size is too large to satisfy.
103  /// \details Internally, preprocessor macros are used rather than std::numeric_limits
104  /// because the latter is not a constexpr. Some compilers, like Clang, do not
105  /// optimize it well under all circumstances. Compilers like GCC, ICC and MSVC appear
106  /// to optimize it well in either form.
107  /// \details The <tt>sizeof(T) != 1</tt> in the condition attempts to help the
108  /// compiler optimize the check for byte types. Coverity findings for
109  /// CONSTANT_EXPRESSION_RESULT were generated without it. For byte types,
110  /// size never exceeded ELEMS_MAX but the code was not removed.
111  /// \note size is the count of elements, and not the number of bytes
112  static void CheckSize(size_t size)
113  {
114  // Squash MSC C4100 warning for size. Also see commit 42b7c4ea5673.
115  CRYPTOPP_UNUSED(size);
116  // C++ throws std::bad_alloc (C++03) or std::bad_array_new_length (C++11) here.
117  if (sizeof(T) != 1 && size > ELEMS_MAX)
118  throw InvalidArgument("AllocatorBase: requested size would cause integer overflow");
119  }
120 };
121 
122 #define CRYPTOPP_INHERIT_ALLOCATOR_TYPES \
123 typedef typename AllocatorBase<T>::value_type value_type;\
124 typedef typename AllocatorBase<T>::size_type size_type;\
125 typedef typename AllocatorBase<T>::difference_type difference_type;\
126 typedef typename AllocatorBase<T>::pointer pointer;\
127 typedef typename AllocatorBase<T>::const_pointer const_pointer;\
128 typedef typename AllocatorBase<T>::reference reference;\
129 typedef typename AllocatorBase<T>::const_reference const_reference;
130 
131 /// \brief Reallocation function
132 /// \tparam T the class or type
133 /// \tparam A the class or type's allocator
134 /// \param alloc the allocator
135 /// \param oldPtr the previous allocation
136 /// \param oldSize the size of the previous allocation
137 /// \param newSize the new, requested size
138 /// \param preserve flag that indicates if the old allocation should be preserved
139 /// \note oldSize and newSize are the count of elements, and not the
140 /// number of bytes.
141 template <class T, class A>
142 typename A::pointer StandardReallocate(A& alloc, T *oldPtr, typename A::size_type oldSize, typename A::size_type newSize, bool preserve)
143 {
144  CRYPTOPP_ASSERT((oldPtr && oldSize) || !(oldPtr || oldSize));
145  if (oldSize == newSize)
146  return oldPtr;
147 
148  if (preserve)
149  {
150  typename A::pointer newPointer = alloc.allocate(newSize, NULLPTR);
151  const size_t copySize = STDMIN(oldSize, newSize) * sizeof(T);
152 
153  if (oldPtr && newPointer) {memcpy_s(newPointer, copySize, oldPtr, copySize);}
154  alloc.deallocate(oldPtr, oldSize);
155  return newPointer;
156  }
157  else
158  {
159  alloc.deallocate(oldPtr, oldSize);
160  return alloc.allocate(newSize, NULLPTR);
161  }
162 }
163 
164 /// \brief Allocates a block of memory with cleanup
165 /// \tparam T class or type
166 /// \tparam T_Align16 boolean that determines whether allocations should be aligned on a 16-byte boundary
167 /// \details If T_Align16 is true, then AllocatorWithCleanup calls AlignedAllocate()
168 /// for memory allocations. If T_Align16 is false, then AllocatorWithCleanup() calls
169 /// UnalignedAllocate() for memory allocations.
170 /// \details Template parameter T_Align16 is effectively controlled by cryptlib.h and mirrors
171 /// CRYPTOPP_BOOL_ALIGN16. CRYPTOPP_BOOL_ALIGN16 is often used as the template parameter.
172 template <class T, bool T_Align16 = false>
174 {
175 public:
176  CRYPTOPP_INHERIT_ALLOCATOR_TYPES
177 
178  /// \brief Allocates a block of memory
179  /// \param ptr the size of the allocation
180  /// \param size the size of the allocation, in elements
181  /// \returns a memory block
182  /// \throws InvalidArgument
183  /// \details allocate() first checks the size of the request. If it is non-0
184  /// and less than max_size(), then an attempt is made to fulfill the request using either
185  /// AlignedAllocate() or UnalignedAllocate().
186  /// \details AlignedAllocate() is used if T_Align16 is true.
187  /// UnalignedAllocate() used if T_Align16 is false.
188  /// \details This is the C++ *Placement New* operator. ptr is not used, and the function
189  /// CRYPTOPP_ASSERTs in Debug builds if ptr is non-NULL.
190  /// \sa CallNewHandler() for the methods used to recover from a failed
191  /// allocation attempt.
192  /// \note size is the count of elements, and not the number of bytes
193  pointer allocate(size_type size, const void *ptr = NULLPTR)
194  {
195  CRYPTOPP_UNUSED(ptr); CRYPTOPP_ASSERT(ptr == NULLPTR);
196  this->CheckSize(size);
197  if (size == 0)
198  return NULLPTR;
199 
200 #if CRYPTOPP_BOOL_ALIGN16
201  // TODO: Does this need the test 'size*sizeof(T) >= 16'?
202  if (T_Align16 && size)
203  return reinterpret_cast<pointer>(AlignedAllocate(size*sizeof(T)));
204 #endif
205 
206  return reinterpret_cast<pointer>(UnalignedAllocate(size*sizeof(T)));
207  }
208 
209  /// \brief Deallocates a block of memory
210  /// \param ptr the pointer for the allocation
211  /// \param size the size of the allocation, in elements
212  /// \details Internally, SecureWipeArray() is called before deallocating the memory.
213  /// Once the memory block is wiped or zeroized, AlignedDeallocate() or
214  /// UnalignedDeallocate() is called.
215  /// \details AlignedDeallocate() is used if T_Align16 is true.
216  /// UnalignedDeallocate() used if T_Align16 is false.
217  void deallocate(void *ptr, size_type size)
218  {
219  // This will fire if SetMark(0) was called in the SecBlock
220  // Our self tests exercise it, disable it now.
221  // CRYPTOPP_ASSERT((ptr && size) || !(ptr || size));
222  SecureWipeArray(reinterpret_cast<pointer>(ptr), size);
223 
224 #if CRYPTOPP_BOOL_ALIGN16
225  if (T_Align16 && size)
226  return AlignedDeallocate(ptr);
227 #endif
228 
229  UnalignedDeallocate(ptr);
230  }
231 
232  /// \brief Reallocates a block of memory
233  /// \param oldPtr the previous allocation
234  /// \param oldSize the size of the previous allocation
235  /// \param newSize the new, requested size
236  /// \param preserve flag that indicates if the old allocation should be preserved
237  /// \returns pointer to the new memory block
238  /// \details Internally, reallocate() calls StandardReallocate().
239  /// \details If preserve is true, then index 0 is used to begin copying the
240  /// old memory block to the new one. If the block grows, then the old array
241  /// is copied in its entirety. If the block shrinks, then only newSize
242  /// elements are copied from the old block to the new one.
243  /// \note oldSize and newSize are the count of elements, and not the
244  /// number of bytes.
245  pointer reallocate(T *oldPtr, size_type oldSize, size_type newSize, bool preserve)
246  {
247  CRYPTOPP_ASSERT((oldPtr && oldSize) || !(oldPtr || oldSize));
248  return StandardReallocate(*this, oldPtr, oldSize, newSize, preserve);
249  }
250 
251  /// \brief Template class memeber Rebind
252  /// \tparam V bound class or type
253  /// \details Rebind allows a container class to allocate a different type of object
254  /// to store elements. For example, a std::list will allocate std::list_node to
255  /// store elements in the list.
256  /// \details VS.NET STL enforces the policy of "All STL-compliant allocators
257  /// have to provide a template class member called rebind".
258  template <class V> struct rebind { typedef AllocatorWithCleanup<V, T_Align16> other; };
259 #if _MSC_VER >= 1500
261  template <class V, bool A> AllocatorWithCleanup(const AllocatorWithCleanup<V, A> &) {}
262 #endif
263 };
264 
265 CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup<byte>;
266 CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup<word16>;
267 CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup<word32>;
268 CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup<word64>;
269 #if defined(CRYPTOPP_WORD128_AVAILABLE)
270 CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup<word128, true>; // for Integer
271 #endif
272 #if CRYPTOPP_BOOL_X86
273 CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup<word, true>; // for Integer
274 #endif
275 
276 /// \brief NULL allocator
277 /// \tparam T class or type
278 /// \details A NullAllocator is useful for fixed-size, stack based allocations
279 /// (i.e., static arrays used by FixedSizeAllocatorWithCleanup).
280 /// \details A NullAllocator always returns 0 for max_size(), and always returns
281 /// NULL for allocation requests. Though the allocator does not allocate at
282 /// runtime, it does perform a secure wipe or zeroization during cleanup.
283 template <class T>
284 class NullAllocator : public AllocatorBase<T>
285 {
286 public:
287  //LCOV_EXCL_START
288  CRYPTOPP_INHERIT_ALLOCATOR_TYPES
289 
290  // TODO: should this return NULL or throw bad_alloc? Non-Windows C++ standard
291  // libraries always throw. And late mode Windows throws. Early model Windows
292  // (circa VC++ 6.0) returned NULL.
293  pointer allocate(size_type n, const void* unused = NULLPTR)
294  {
295  CRYPTOPP_UNUSED(n); CRYPTOPP_UNUSED(unused);
296  CRYPTOPP_ASSERT(false); return NULLPTR;
297  }
298 
299  void deallocate(void *p, size_type n)
300  {
301  CRYPTOPP_UNUSED(p); CRYPTOPP_UNUSED(n);
302  CRYPTOPP_ASSERT(false);
303  }
304 
305  CRYPTOPP_CONSTEXPR size_type max_size() const {return 0;}
306  //LCOV_EXCL_STOP
307 };
308 
309 /// \brief Static secure memory block with cleanup
310 /// \tparam T class or type
311 /// \tparam S fixed-size of the stack-based memory block, in elements
312 /// \tparam T_Align16 boolean that determines whether allocations should
313 /// be aligned on a 16-byte boundary
314 /// \details FixedSizeAllocatorWithCleanup provides a fixed-size, stack-
315 /// based allocation at compile time. The class can grow its memory
316 /// block at runtime if a suitable allocator is available. If size
317 /// grows beyond S and a suitable allocator is available, then the
318 /// statically allocated array is obsoleted.
319 /// \note This allocator can't be used with standard collections because
320 /// they require that all objects of the same allocator type are equivalent.
321 template <class T, size_t S, class A = NullAllocator<T>, bool T_Align16 = false>
323 {
324  // The body of FixedSizeAllocatorWithCleanup is provided in the two
325  // partial specializations that follow. The two specialiations
326  // pivot on the boolean template parameter T_Align16. AIX, Solaris,
327  // IBM XLC and SunCC receive a little extra help. We managed to
328  // clear most of the warnings.
329 };
330 
331 /// \brief Static secure memory block with cleanup
332 /// \tparam T class or type
333 /// \tparam S fixed-size of the stack-based memory block, in elements
334 /// \details FixedSizeAllocatorWithCleanup provides a fixed-size, stack-
335 /// based allocation at compile time. The class can grow its memory
336 /// block at runtime if a suitable allocator is available. If size
337 /// grows beyond S and a suitable allocator is available, then the
338 /// statically allocated array is obsoleted.
339 /// \note This allocator can't be used with standard collections because
340 /// they require that all objects of the same allocator type are equivalent.
341 template <class T, size_t S, class A>
342 class FixedSizeAllocatorWithCleanup<T, S, A, true> : public AllocatorBase<T>
343 {
344 public:
345  CRYPTOPP_INHERIT_ALLOCATOR_TYPES
346 
347  /// \brief Constructs a FixedSizeAllocatorWithCleanup
348  FixedSizeAllocatorWithCleanup() : m_allocated(false) {}
349 
350  /// \brief Allocates a block of memory
351  /// \param size the count elements in the memory block
352  /// \details FixedSizeAllocatorWithCleanup provides a fixed-size, stack-based
353  /// allocation at compile time. If size is less than or equal to
354  /// <tt>S</tt>, then a pointer to the static array is returned.
355  /// \details The class can grow its memory block at runtime if a suitable
356  /// allocator is available. If size grows beyond S and a suitable
357  /// allocator is available, then the statically allocated array is
358  /// obsoleted. If a suitable allocator is not available, as with a
359  /// NullAllocator, then the function returns NULL and a runtime error
360  /// eventually occurs.
361  /// \sa reallocate(), SecBlockWithHint
362  pointer allocate(size_type size)
363  {
364  CRYPTOPP_ASSERT(IsAlignedOn(m_array, 8));
365 
366  if (size <= S && !m_allocated)
367  {
368  m_allocated = true;
369  return GetAlignedArray();
370  }
371  else
372  return m_fallbackAllocator.allocate(size);
373  }
374 
375  /// \brief Allocates a block of memory
376  /// \param size the count elements in the memory block
377  /// \param hint an unused hint
378  /// \details FixedSizeAllocatorWithCleanup provides a fixed-size, stack-
379  /// based allocation at compile time. If size is less than or equal to
380  /// S, then a pointer to the static array is returned.
381  /// \details The class can grow its memory block at runtime if a suitable
382  /// allocator is available. If size grows beyond S and a suitable
383  /// allocator is available, then the statically allocated array is
384  /// obsoleted. If a suitable allocator is not available, as with a
385  /// NullAllocator, then the function returns NULL and a runtime error
386  /// eventually occurs.
387  /// \sa reallocate(), SecBlockWithHint
388  pointer allocate(size_type size, const void *hint)
389  {
390  if (size <= S && !m_allocated)
391  {
392  m_allocated = true;
393  return GetAlignedArray();
394  }
395  else
396  return m_fallbackAllocator.allocate(size, hint);
397  }
398 
399  /// \brief Deallocates a block of memory
400  /// \param ptr a pointer to the memory block to deallocate
401  /// \param size the count elements in the memory block
402  /// \details The memory block is wiped or zeroized before deallocation.
403  /// If the statically allocated memory block is active, then no
404  /// additional actions are taken after the wipe.
405  /// \details If a dynamic memory block is active, then the pointer and
406  /// size are passed to the allocator for deallocation.
407  void deallocate(void *ptr, size_type size)
408  {
409  if (ptr == GetAlignedArray())
410  {
411  // If the m_allocated assert fires then the bit twiddling for
412  // GetAlignedArray() is probably incorrect for the platform.
413  // Be sure to check CRYPTOPP_ALIGN_DATA(8). The platform may
414  // not have a way to declaritively align data to 8.
415  CRYPTOPP_ASSERT(size <= S);
416  CRYPTOPP_ASSERT(m_allocated);
417  m_allocated = false;
418  SecureWipeArray((pointer)ptr, size);
419  }
420  else
421  m_fallbackAllocator.deallocate(ptr, size);
422  }
423 
424  /// \brief Reallocates a block of memory
425  /// \param oldPtr the previous allocation
426  /// \param oldSize the size of the previous allocation
427  /// \param newSize the new, requested size
428  /// \param preserve flag that indicates if the old allocation should
429  /// 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
463  {
464  return STDMAX(m_fallbackAllocator.max_size(), S);
465  }
466 
467 private:
468 
469 #if defined(CRYPTOPP_BOOL_ALIGN16) && (defined(_M_X64) || defined(__x86_64__))
470  // Before we can add additional platforms we need to check the
471  // linker documentation for alignment behavior for stack variables.
472  // CRYPTOPP_ALIGN_DATA(16) is known OK on Linux, OS X, Solaris.
473  // Also see http://stackoverflow.com/a/1468656/608639.
474  T* GetAlignedArray() {
475  CRYPTOPP_ASSERT(IsAlignedOn(m_array, 16));
476  return m_array;
477  }
478  CRYPTOPP_ALIGN_DATA(16) T m_array[S];
479 
480 #elif defined(CRYPTOPP_BOOL_ALIGN16)
481 
482  // There be demons here... We cannot use CRYPTOPP_ALIGN_DATA(16)
483  // because linkers on 32-bit machines (and some 64-bit machines)
484  // align the stack to 8-bytes or less by default, not 16-bytes as
485  // requested. Additionally, the AIX linker seems to use 4-bytes
486  // by default. However, all linkers tested appear to honor
487  // CRYPTOPP_ALIGN_DATA(8). Also see
488  // http://stackoverflow.com/a/1468656/608639.
489  //
490  // The 16-byte alignment is achieved by padding the requested
491  // size with extra elements so we have at least 16-bytes of slack
492  // to work with. Then the pointer is moved down to achieve a
493  // 16-byte alignment (stacks grow down).
494  //
495  // The additional 16-bytes introduces a small secondary issue.
496  // The secondary issue is, a large T results in 0 = 8/sizeof(T).
497  // The library is OK but users may hit it. So we need to guard
498  // for a large T, and that is what PAD achieves.
499  T* GetAlignedArray() {
500  T* p_array = (T*)(void*)(((byte*)m_array) + (0-(size_t)m_array)%16);
501  // Verify the 16-byte alignment
502  CRYPTOPP_ASSERT(IsAlignedOn(p_array, 16));
503  // Verify allocated array with pad is large enough.
504  CRYPTOPP_ASSERT(p_array+S <= m_array+(S+PAD));
505  return p_array;
506  }
507 
508 # if defined(_AIX)
509  // PAD is elements, not bytes, and rounded up to ensure no overflow.
510  enum { Q = sizeof(T), PAD = (Q >= 16) ? 1 : (Q >= 8) ? 2 : (Q >= 4) ? 4 : (Q >= 2) ? 8 : 16 };
511  CRYPTOPP_ALIGN_DATA(8) T m_array[S+PAD];
512 # else
513  // PAD is elements, not bytes, and rounded up to ensure no overflow.
514  enum { Q = sizeof(T), PAD = (Q >= 8) ? 1 : (Q >= 4) ? 2 : (Q >= 2) ? 4 : 8 };
515  CRYPTOPP_ALIGN_DATA(8) T m_array[S+PAD];
516 # endif
517 
518 #else
519 
520  // CRYPTOPP_BOOL_ALIGN16 is 0. Use natural alignment of T.
521  T* GetAlignedArray() {return m_array;}
522  CRYPTOPP_ALIGN_DATA(4) T m_array[S];
523 
524 #endif
525 
526  A m_fallbackAllocator;
527  bool m_allocated;
528 };
529 
530 /// \brief Static secure memory block with cleanup
531 /// \tparam T class or type
532 /// \tparam S fixed-size of the stack-based memory block, in elements
533 /// \details FixedSizeAllocatorWithCleanup provides a fixed-size, stack-
534 /// based allocation at compile time. The class can grow its memory
535 /// block at runtime if a suitable allocator is available. If size
536 /// grows beyond S and a suitable allocator is available, then the
537 /// statically allocated array is obsoleted.
538 /// \note This allocator can't be used with standard collections because
539 /// they require that all objects of the same allocator type are equivalent.
540 template <class T, size_t S, class A>
541 class FixedSizeAllocatorWithCleanup<T, S, A, false> : public AllocatorBase<T>
542 {
543 public:
544  CRYPTOPP_INHERIT_ALLOCATOR_TYPES
545 
546  /// \brief Constructs a FixedSizeAllocatorWithCleanup
547  FixedSizeAllocatorWithCleanup() : m_allocated(false) {}
548 
549  /// \brief Allocates a block of memory
550  /// \param size the count elements in the memory block
551  /// \details FixedSizeAllocatorWithCleanup provides a fixed-size, stack-based
552  /// allocation at compile time. If size is less than or equal to
553  /// <tt>S</tt>, then a pointer to the static array is returned.
554  /// \details The class can grow its memory block at runtime if a suitable
555  /// allocator is available. If size grows beyond S and a suitable
556  /// allocator is available, then the statically allocated array is
557  /// obsoleted. If a suitable allocator is not available, as with a
558  /// NullAllocator, then the function returns NULL and a runtime error
559  /// eventually occurs.
560  /// \sa reallocate(), SecBlockWithHint
561  pointer allocate(size_type size)
562  {
563  CRYPTOPP_ASSERT(IsAlignedOn(m_array, 8));
564 
565  if (size <= S && !m_allocated)
566  {
567  m_allocated = true;
568  return GetAlignedArray();
569  }
570  else
571  return m_fallbackAllocator.allocate(size);
572  }
573 
574  /// \brief Allocates a block of memory
575  /// \param size the count elements in the memory block
576  /// \param hint an unused hint
577  /// \details FixedSizeAllocatorWithCleanup provides a fixed-size, stack-
578  /// based allocation at compile time. If size is less than or equal to
579  /// S, then a pointer to the static array is returned.
580  /// \details The class can grow its memory block at runtime if a suitable
581  /// allocator is available. If size grows beyond S and a suitable
582  /// allocator is available, then the statically allocated array is
583  /// obsoleted. If a suitable allocator is not available, as with a
584  /// NullAllocator, then the function returns NULL and a runtime error
585  /// eventually occurs.
586  /// \sa reallocate(), SecBlockWithHint
587  pointer allocate(size_type size, const void *hint)
588  {
589  if (size <= S && !m_allocated)
590  {
591  m_allocated = true;
592  return GetAlignedArray();
593  }
594  else
595  return m_fallbackAllocator.allocate(size, hint);
596  }
597 
598  /// \brief Deallocates a block of memory
599  /// \param ptr a pointer to the memory block to deallocate
600  /// \param size the count elements in the memory block
601  /// \details The memory block is wiped or zeroized before deallocation.
602  /// If the statically allocated memory block is active, then no
603  /// additional actions are taken after the wipe.
604  /// \details If a dynamic memory block is active, then the pointer and
605  /// size are passed to the allocator for deallocation.
606  void deallocate(void *ptr, size_type size)
607  {
608  if (ptr == GetAlignedArray())
609  {
610  // If the m_allocated assert fires then
611  // something overwrote the flag.
612  CRYPTOPP_ASSERT(size <= S);
613  CRYPTOPP_ASSERT(m_allocated);
614  m_allocated = false;
615  SecureWipeArray((pointer)ptr, size);
616  }
617  else
618  m_fallbackAllocator.deallocate(ptr, size);
619  }
620 
621  /// \brief Reallocates a block of memory
622  /// \param oldPtr the previous allocation
623  /// \param oldSize the size of the previous allocation
624  /// \param newSize the new, requested size
625  /// \param preserve flag that indicates if the old allocation should
626  /// be preserved
627  /// \returns pointer to the new memory block
628  /// \details FixedSizeAllocatorWithCleanup provides a fixed-size, stack-
629  /// based allocation at compile time. If size is less than or equal to
630  /// S, then a pointer to the static array is returned.
631  /// \details The class can grow its memory block at runtime if a suitable
632  /// allocator is available. If size grows beyond S and a suitable
633  /// allocator is available, then the statically allocated array is
634  /// obsoleted. If a suitable allocator is not available, as with a
635  /// NullAllocator, then the function returns NULL and a runtime error
636  /// eventually occurs.
637  /// \note size is the count of elements, and not the number of bytes.
638  /// \sa reallocate(), SecBlockWithHint
639  pointer reallocate(pointer oldPtr, size_type oldSize, size_type newSize, bool preserve)
640  {
641  if (oldPtr == GetAlignedArray() && newSize <= S)
642  {
643  CRYPTOPP_ASSERT(oldSize <= S);
644  if (oldSize > newSize)
645  SecureWipeArray(oldPtr+newSize, oldSize-newSize);
646  return oldPtr;
647  }
648 
649  pointer newPointer = allocate(newSize, NULLPTR);
650  if (preserve && newSize)
651  {
652  const size_t copySize = STDMIN(oldSize, newSize);
653  memcpy_s(newPointer, sizeof(T)*newSize, oldPtr, sizeof(T)*copySize);
654  }
655  deallocate(oldPtr, oldSize);
656  return newPointer;
657  }
658 
659  CRYPTOPP_CONSTEXPR size_type max_size() const
660  {
661  return STDMAX(m_fallbackAllocator.max_size(), S);
662  }
663 
664 private:
665 
666  // The 8-byte alignments follows convention of Linux and Windows.
667  // Linux and Windows receives most testing. Duplicate it here for
668  // other platforms like AIX and Solaris. AIX and Solaris often use
669  // alignments smaller than expected. In fact AIX caught us by
670  // surprise with word16 and word32.
671  T* GetAlignedArray() {return m_array;}
672  CRYPTOPP_ALIGN_DATA(8) T m_array[S];
673 
674  A m_fallbackAllocator;
675  bool m_allocated;
676 };
677 
678 /// \brief Secure memory block with allocator and cleanup
679 /// \tparam T a class or type
680 /// \tparam A AllocatorWithCleanup derived class for allocation and cleanup
681 template <class T, class A = AllocatorWithCleanup<T> >
682 class SecBlock
683 {
684 public:
685  typedef typename A::value_type value_type;
686  typedef typename A::pointer iterator;
687  typedef typename A::const_pointer const_iterator;
688  typedef typename A::size_type size_type;
689 
690  /// \brief Returns the maximum number of elements the block can hold
691  /// \details <tt>ELEMS_MAX</tt> is the maximum number of elements the
692  /// <tt>SecBlock</tt> can hold. The value of <tt>ELEMS_MAX</tt> is
693  /// <tt>SIZE_MAX/sizeof(T)</tt>. <tt>std::numeric_limits</tt> was avoided
694  /// due to lack of <tt>constexpr</tt>-ness in C++03 and below.
695  /// \note In C++03 and below <tt>ELEMS_MAX</tt> is a static data member of type
696  /// <tt>size_type</tt>. In C++11 and above <tt>ELEMS_MAX</tt> is an <tt>enum</tt>
697  /// inheriting from <tt>size_type</tt>. In both cases <tt>ELEMS_MAX</tt> can be
698  /// used before objects are fully constructed, and it does not suffer the
699  /// limitations of class methods like <tt>max_size</tt>.
700  /// \sa <A HREF="http://github.com/weidai11/cryptopp/issues/346">Issue 346/CVE-2016-9939</A>
701  /// \since Crypto++ 6.0
702 #if defined(CRYPTOPP_DOXYGEN_PROCESSING)
703  static const size_type ELEMS_MAX = ...;
704 #elif defined(_MSC_VER) && (_MSC_VER <= 1400)
705  static const size_type ELEMS_MAX = (~(size_type)0)/sizeof(T);
706 #elif defined(CRYPTOPP_CXX11_ENUM)
707  enum : size_type {ELEMS_MAX = A::ELEMS_MAX};
708 #else
709  static const size_type ELEMS_MAX = SIZE_MAX/sizeof(T);
710 #endif
711 
712  /// \brief Construct a SecBlock with space for size elements.
713  /// \param size the size of the allocation, in elements
714  /// \throws std::bad_alloc
715  /// \details The elements are not initialized.
716  /// \note size is the count of elements, and not the number of bytes
717  explicit SecBlock(size_type size=0)
718  : m_mark(ELEMS_MAX), m_size(size), m_ptr(m_alloc.allocate(size, NULLPTR)) { }
719 
720  /// \brief Copy construct a SecBlock from another SecBlock
721  /// \param t the other SecBlock
722  /// \throws std::bad_alloc
724  : m_mark(t.m_mark), m_size(t.m_size), m_ptr(m_alloc.allocate(t.m_size, NULLPTR)) {
725  CRYPTOPP_ASSERT((!t.m_ptr && !m_size) || (t.m_ptr && m_size));
726  if (t.m_ptr) {memcpy_s(m_ptr, m_size*sizeof(T), t.m_ptr, t.m_size*sizeof(T));}
727  }
728 
729  /// \brief Construct a SecBlock from an array of elements.
730  /// \param ptr a pointer to an array of T
731  /// \param len the number of elements in the memory block
732  /// \throws std::bad_alloc
733  /// \details If <tt>ptr!=NULL</tt> and <tt>len!=0</tt>, then the block is initialized from the pointer
734  /// <tt>ptr</tt>. If <tt>ptr==NULL</tt> and <tt>len!=0</tt>, then the block is initialized to 0.
735  /// Otherwise, the block is empty and not initialized.
736  /// \note size is the count of elements, and not the number of bytes
737  SecBlock(const T *ptr, size_type len)
738  : m_mark(ELEMS_MAX), m_size(len), m_ptr(m_alloc.allocate(len, NULLPTR)) {
739  CRYPTOPP_ASSERT((!m_ptr && !m_size) || (m_ptr && m_size));
740  if (ptr && m_ptr)
741  memcpy_s(m_ptr, m_size*sizeof(T), ptr, len*sizeof(T));
742  else if (m_size)
743  memset(m_ptr, 0, m_size*sizeof(T));
744  }
745 
746  ~SecBlock()
747  {m_alloc.deallocate(m_ptr, STDMIN(m_size, m_mark));}
748 
749 #ifdef __BORLANDC__
750  operator T *() const
751  {return (T*)m_ptr;}
752 #else
753  operator const void *() const
754  {return m_ptr;}
755  operator void *()
756  {return m_ptr;}
757 
758  operator const T *() const
759  {return m_ptr;}
760  operator T *()
761  {return m_ptr;}
762 #endif
763 
764  /// \brief Provides an iterator pointing to the first element in the memory block
765  /// \returns iterator pointing to the first element in the memory block
766  iterator begin()
767  {return m_ptr;}
768  /// \brief Provides a constant iterator pointing to the first element in the memory block
769  /// \returns constant iterator pointing to the first element in the memory block
770  const_iterator begin() const
771  {return m_ptr;}
772  /// \brief Provides an iterator pointing beyond the last element in the memory block
773  /// \returns iterator pointing beyond the last element in the memory block
774  iterator end()
775  {return m_ptr+m_size;}
776  /// \brief Provides a constant iterator pointing beyond the last element in the memory block
777  /// \returns constant iterator pointing beyond the last element in the memory block
778  const_iterator end() const
779  {return m_ptr+m_size;}
780 
781  /// \brief Provides a pointer to the first element in the memory block
782  /// \returns pointer to the first element in the memory block
783  typename A::pointer data() {return m_ptr;}
784  /// \brief Provides a pointer to the first element in the memory block
785  /// \returns constant pointer to the first element in the memory block
786  typename A::const_pointer data() const {return m_ptr;}
787 
788  /// \brief Provides the count of elements in the SecBlock
789  /// \returns number of elements in the memory block
790  /// \note the return value is the count of elements, and not the number of bytes
791  size_type size() const {return m_size;}
792  /// \brief Determines if the SecBlock is empty
793  /// \returns true if number of elements in the memory block is 0, false otherwise
794  bool empty() const {return m_size == 0;}
795 
796  /// \brief Provides a byte pointer to the first element in the memory block
797  /// \returns byte pointer to the first element in the memory block
798  byte * BytePtr() {return (byte *)m_ptr;}
799  /// \brief Return a byte pointer to the first element in the memory block
800  /// \returns constant byte pointer to the first element in the memory block
801  const byte * BytePtr() const {return (const byte *)m_ptr;}
802  /// \brief Provides the number of bytes in the SecBlock
803  /// \return the number of bytes in the memory block
804  /// \note the return value is the number of bytes, and not count of elements.
805  size_type SizeInBytes() const {return m_size*sizeof(T);}
806 
807  /// \brief Sets the number of elements to zeroize
808  /// \param count the number of elements
809  /// \details SetMark is a remediation for Issue 346/CVE-2016-9939 while
810  /// preserving the streaming interface. The <tt>count</tt> controls the number of
811  /// elements zeroized, which can be less than <tt>size</tt> or 0.
812  /// \details An internal variable, <tt>m_mark</tt>, is initialized to the maximum number
813  /// of elements. The maximum number of elements is <tt>ELEMS_MAX</tt>. Deallocation
814  /// triggers a zeroization, and the number of elements zeroized is
815  /// <tt>STDMIN(m_size, m_mark)</tt>. After zeroization, the memory is returned to the
816  /// system.
817  /// \details The ASN.1 decoder uses SetMark() to set the element count to 0
818  /// before throwing an exception. In this case, the attacker provides a large
819  /// BER encoded length (say 64MB) but only a small number of content octets
820  /// (say 16). If the allocator zeroized all 64MB, then a transient DoS could
821  /// occur as CPU cycles are spent zeroizing unintialized memory.
822  /// \details Generally speaking, any operation which changes the size of the SecBlock
823  /// results in the mark being reset to <tt>ELEMS_MAX</tt>. In particular, if Assign(),
824  /// New(), Grow(), CleanNew(), CleanGrow() are called, then the count is reset to
825  /// <tt>ELEMS_MAX</tt>. The list is not exhaustive.
826  /// \since Crypto++ 6.0
827  /// \sa <A HREF="http://github.com/weidai11/cryptopp/issues/346">Issue 346/CVE-2016-9939</A>
828  void SetMark(size_t count) {m_mark = count;}
829 
830  /// \brief Set contents and size from an array
831  /// \param ptr a pointer to an array of T
832  /// \param len the number of elements in the memory block
833  /// \details If the memory block is reduced in size, then the reclaimed memory is set to 0.
834  /// Assign() resets the element count after the previous block is zeroized.
835  void Assign(const T *ptr, size_type len)
836  {
837  New(len);
838  if (m_ptr && ptr)
839  {memcpy_s(m_ptr, m_size*sizeof(T), ptr, len*sizeof(T));}
840  m_mark = ELEMS_MAX;
841  }
842 
843  /// \brief Set contents from a value
844  /// \param count the number of values to copy
845  /// \param value the value, repeated count times
846  /// \details If the memory block is reduced in size, then the reclaimed memory is set to 0.
847  /// Assign() resets the element count after the previous block is zeroized.
848  void Assign(size_type count, T value)
849  {
850  New(count);
851  for (size_t i=0; i<count; ++i)
852  m_ptr[i] = value;
853 
854  m_mark = ELEMS_MAX;
855  }
856 
857  /// \brief Copy contents from another SecBlock
858  /// \param t the other SecBlock
859  /// \details Assign checks for self assignment.
860  /// \details If the memory block is reduced in size, then the reclaimed memory is set to 0.
861  /// If an assignment occurs, then Assign() resets the element count after the previous block
862  /// is zeroized.
863  void Assign(const SecBlock<T, A> &t)
864  {
865  if (this != &t)
866  {
867  New(t.m_size);
868  if (m_ptr && t.m_ptr)
869  {memcpy_s(m_ptr, m_size*sizeof(T), t, t.m_size*sizeof(T));}
870  }
871  m_mark = ELEMS_MAX;
872  }
873 
874  /// \brief Assign contents from another SecBlock
875  /// \param t the other SecBlock
876  /// \details Internally, operator=() calls Assign().
877  /// \details If the memory block is reduced in size, then the reclaimed memory is set to 0.
878  /// If an assignment occurs, then Assign() resets the element count after the previous block
879  /// is zeroized.
881  {
882  // Assign guards for self-assignment
883  Assign(t);
884  return *this;
885  }
886 
887  /// \brief Append contents from another SecBlock
888  /// \param t the other SecBlock
889  /// \details Internally, this SecBlock calls Grow and then appends t.
891  {
892  CRYPTOPP_ASSERT((!t.m_ptr && !t.m_size) || (t.m_ptr && t.m_size));
893  if (t.m_size)
894  {
895  const size_type oldSize = m_size;
896  if (this != &t) // s += t
897  {
898  Grow(m_size+t.m_size);
899  memcpy_s(m_ptr+oldSize, (m_size-oldSize)*sizeof(T), t.m_ptr, t.m_size*sizeof(T));
900  }
901  else // t += t
902  {
903  Grow(m_size*2);
904  memcpy_s(m_ptr+oldSize, (m_size-oldSize)*sizeof(T), m_ptr, oldSize*sizeof(T));
905  }
906  }
907  m_mark = ELEMS_MAX;
908  return *this;
909  }
910 
911  /// \brief Construct a SecBlock from this and another SecBlock
912  /// \param t the other SecBlock
913  /// \returns a newly constructed SecBlock that is a conacentation of this and t
914  /// \details Internally, a new SecBlock is created from this and a concatenation of t.
916  {
917  CRYPTOPP_ASSERT((!m_ptr && !m_size) || (m_ptr && m_size));
918  CRYPTOPP_ASSERT((!t.m_ptr && !t.m_size) || (t.m_ptr && t.m_size));
919  if(!t.m_size) return SecBlock(*this);
920 
921  SecBlock<T, A> result(m_size+t.m_size);
922  if (m_size) {memcpy_s(result.m_ptr, result.m_size*sizeof(T), m_ptr, m_size*sizeof(T));}
923  memcpy_s(result.m_ptr+m_size, (result.m_size-m_size)*sizeof(T), t.m_ptr, t.m_size*sizeof(T));
924  return result;
925  }
926 
927  /// \brief Bitwise compare two SecBlocks
928  /// \param t the other SecBlock
929  /// \returns true if the size and bits are equal, false otherwise
930  /// \details Uses a constant time compare if the arrays are equal size. The constant time
931  /// compare is VerifyBufsEqual() found in misc.h.
932  /// \sa operator!=()
933  bool operator==(const SecBlock<T, A> &t) const
934  {
935  return m_size == t.m_size &&
936  VerifyBufsEqual(reinterpret_cast<const byte*>(m_ptr), reinterpret_cast<const byte*>(t.m_ptr), m_size*sizeof(T));
937  }
938 
939  /// \brief Bitwise compare two SecBlocks
940  /// \param t the other SecBlock
941  /// \returns true if the size and bits are equal, false otherwise
942  /// \details Uses a constant time compare if the arrays are equal size. The constant time
943  /// compare is VerifyBufsEqual() found in misc.h.
944  /// \details Internally, operator!=() returns the inverse of operator==().
945  /// \sa operator==()
946  bool operator!=(const SecBlock<T, A> &t) const
947  {
948  return !operator==(t);
949  }
950 
951  /// \brief Change size without preserving contents
952  /// \param newSize the new size of the memory block
953  /// \details Old content is not preserved. If the memory block is reduced in size,
954  /// then the reclaimed memory is set to 0. If the memory block grows in size, then
955  /// the new memory is not initialized. New() resets the element count after the
956  /// previous block is zeroized.
957  /// \details Internally, this SecBlock calls reallocate().
958  /// \sa New(), CleanNew(), Grow(), CleanGrow(), resize()
959  void New(size_type newSize)
960  {
961  m_ptr = m_alloc.reallocate(m_ptr, m_size, newSize, false);
962  m_size = newSize;
963  m_mark = ELEMS_MAX;
964  }
965 
966  /// \brief Change size without preserving contents
967  /// \param newSize the new size of the memory block
968  /// \details Old content is not preserved. If the memory block is reduced in size,
969  /// then the reclaimed content is set to 0. If the memory block grows in size, then
970  /// the new memory is initialized to 0. CleanNew() resets the element count after the
971  /// previous block is zeroized.
972  /// \details Internally, this SecBlock calls New().
973  /// \sa New(), CleanNew(), Grow(), CleanGrow(), resize()
974  void CleanNew(size_type newSize)
975  {
976  New(newSize);
977  if (m_ptr) {memset_z(m_ptr, 0, m_size*sizeof(T));}
978  m_mark = ELEMS_MAX;
979  }
980 
981  /// \brief Change size and preserve contents
982  /// \param newSize the new size of the memory block
983  /// \details Old content is preserved. New content is not initialized.
984  /// \details Internally, this SecBlock calls reallocate() when size must increase. If the
985  /// size does not increase, then Grow() does not take action. If the size must
986  /// change, then use resize(). Grow() resets the element count after the
987  /// previous block is zeroized.
988  /// \sa New(), CleanNew(), Grow(), CleanGrow(), resize()
989  void Grow(size_type newSize)
990  {
991  if (newSize > m_size)
992  {
993  m_ptr = m_alloc.reallocate(m_ptr, m_size, newSize, true);
994  m_size = newSize;
995  }
996  m_mark = ELEMS_MAX;
997  }
998 
999  /// \brief Change size and preserve contents
1000  /// \param newSize the new size of the memory block
1001  /// \details Old content is preserved. New content is initialized to 0.
1002  /// \details Internally, this SecBlock calls reallocate() when size must increase. If the
1003  /// size does not increase, then CleanGrow() does not take action. If the size must
1004  /// change, then use resize(). CleanGrow() resets the element count after the
1005  /// previous block is zeroized.
1006  /// \sa New(), CleanNew(), Grow(), CleanGrow(), resize()
1007  void CleanGrow(size_type newSize)
1008  {
1009  if (newSize > m_size)
1010  {
1011  m_ptr = m_alloc.reallocate(m_ptr, m_size, newSize, true);
1012  memset_z(m_ptr+m_size, 0, (newSize-m_size)*sizeof(T));
1013  m_size = newSize;
1014  }
1015  m_mark = ELEMS_MAX;
1016  }
1017 
1018  /// \brief Change size and preserve contents
1019  /// \param newSize the new size of the memory block
1020  /// \details Old content is preserved. If the memory block grows in size, then
1021  /// new memory is not initialized. resize() resets the element count after
1022  /// the previous block is zeroized.
1023  /// \details Internally, this SecBlock calls reallocate().
1024  /// \sa New(), CleanNew(), Grow(), CleanGrow(), resize()
1025  void resize(size_type newSize)
1026  {
1027  m_ptr = m_alloc.reallocate(m_ptr, m_size, newSize, true);
1028  m_size = newSize;
1029  m_mark = ELEMS_MAX;
1030  }
1031 
1032  /// \brief Swap contents with another SecBlock
1033  /// \param b the other SecBlock
1034  /// \details Internally, std::swap() is called on m_alloc, m_size and m_ptr.
1036  {
1037  // Swap must occur on the allocator in case its FixedSize that spilled into the heap.
1038  std::swap(m_alloc, b.m_alloc);
1039  std::swap(m_mark, b.m_mark);
1040  std::swap(m_size, b.m_size);
1041  std::swap(m_ptr, b.m_ptr);
1042  }
1043 
1044 protected:
1045  A m_alloc;
1046  size_type m_mark, m_size;
1047  T *m_ptr;
1048 };
1049 
1050 #ifdef CRYPTOPP_DOXYGEN_PROCESSING
1051 /// \brief \ref SecBlock "SecBlock<byte>" typedef.
1052 class SecByteBlock : public SecBlock<byte> {};
1053 /// \brief \ref SecBlock "SecBlock<word>" typedef.
1054 class SecWordBlock : public SecBlock<word> {};
1055 /// \brief SecBlock using \ref AllocatorWithCleanup "AllocatorWithCleanup<byte, true>" typedef
1056 class AlignedSecByteBlock : public SecBlock<byte, AllocatorWithCleanup<byte, true> > {};
1057 #else
1061 #endif
1062 
1063 // No need for move semantics on derived class *if* the class does not add any
1064 // data members; see http://stackoverflow.com/q/31755703, and Rule of {0|3|5}.
1065 
1066 /// \brief Fixed size stack-based SecBlock
1067 /// \tparam T class or type
1068 /// \tparam S fixed-size of the stack-based memory block, in elements
1069 /// \tparam A AllocatorBase derived class for allocation and cleanup
1070 template <class T, unsigned int S, class A = FixedSizeAllocatorWithCleanup<T, S> >
1071 class FixedSizeSecBlock : public SecBlock<T, A>
1072 {
1073 public:
1074  /// \brief Construct a FixedSizeSecBlock
1075  explicit FixedSizeSecBlock() : SecBlock<T, A>(S) {}
1076 };
1077 
1078 /// \brief Fixed size stack-based SecBlock with 16-byte alignment
1079 /// \tparam T class or type
1080 /// \tparam S fixed-size of the stack-based memory block, in elements
1081 /// \tparam T_Align16 boolean that determines whether allocations should be aligned on a 16-byte boundary
1082 template <class T, unsigned int S, bool T_Align16 = true>
1083 class FixedSizeAlignedSecBlock : public FixedSizeSecBlock<T, S, FixedSizeAllocatorWithCleanup<T, S, NullAllocator<T>, T_Align16> >
1084 {
1085 };
1086 
1087 /// \brief Stack-based SecBlock that grows into the heap
1088 /// \tparam T class or type
1089 /// \tparam S fixed-size of the stack-based memory block, in elements
1090 /// \tparam A AllocatorBase derived class for allocation and cleanup
1091 template <class T, unsigned int S, class A = FixedSizeAllocatorWithCleanup<T, S, AllocatorWithCleanup<T> > >
1092 class SecBlockWithHint : public SecBlock<T, A>
1093 {
1094 public:
1095  /// construct a SecBlockWithHint with a count of elements
1096  explicit SecBlockWithHint(size_t size) : SecBlock<T, A>(size) {}
1097 };
1098 
1099 template<class T, bool A, class V, bool B>
1100 inline bool operator==(const CryptoPP::AllocatorWithCleanup<T, A>&, const CryptoPP::AllocatorWithCleanup<V, B>&) {return (true);}
1101 template<class T, bool A, class V, bool B>
1102 inline bool operator!=(const CryptoPP::AllocatorWithCleanup<T, A>&, const CryptoPP::AllocatorWithCleanup<V, B>&) {return (false);}
1103 
1104 NAMESPACE_END
1105 
1106 NAMESPACE_BEGIN(std)
1107 template <class T, class A>
1108 inline void swap(CryptoPP::SecBlock<T, A> &a, CryptoPP::SecBlock<T, A> &b)
1109 {
1110  a.swap(b);
1111 }
1112 
1113 #if defined(_STLP_DONT_SUPPORT_REBIND_MEMBER_TEMPLATE) || (defined(_STLPORT_VERSION) && !defined(_STLP_MEMBER_TEMPLATE_CLASSES))
1114 // working for STLport 5.1.3 and MSVC 6 SP5
1115 template <class _Tp1, class _Tp2>
1116 inline CryptoPP::AllocatorWithCleanup<_Tp2>&
1117 __stl_alloc_rebind(CryptoPP::AllocatorWithCleanup<_Tp1>& __a, const _Tp2*)
1118 {
1119  return (CryptoPP::AllocatorWithCleanup<_Tp2>&)(__a);
1120 }
1121 #endif
1122 
1123 NAMESPACE_END
1124 
1125 #if CRYPTOPP_MSC_VERSION
1126 # pragma warning(pop)
1127 #endif
1128 
1129 #endif
iterator end()
Provides an iterator pointing beyond the last element in the memory block.
Definition: secblock.h:774
An invalid argument was detected.
Definition: cryptlib.h:202
void construct(V *ptr, Args &&... args)
Constructs a new V using variadic arguments.
Definition: secblock.h:84
Base class for all allocators used by SecBlock.
Definition: secblock.h:28
void swap(SecBlock< T, A > &b)
Swap contents with another SecBlock.
Definition: secblock.h:1035
Stack-based SecBlock that grows into the heap.
Definition: secblock.h:1092
Utility functions for the Crypto++ library.
void AlignedDeallocate(void *ptr)
Frees a buffer allocated with AlignedAllocate.
FixedSizeSecBlock()
Construct a FixedSizeSecBlock.
Definition: secblock.h:1075
void CleanNew(size_type newSize)
Change size without preserving contents.
Definition: secblock.h:974
SecBlock< T, A > & operator=(const SecBlock< T, A > &t)
Assign contents from another SecBlock.
Definition: secblock.h:880
size_type SizeInBytes() const
Provides the number of bytes in the SecBlock.
Definition: secblock.h:805
void resize(size_type newSize)
Change size and preserve contents.
Definition: secblock.h:1025
SecBlock< T, A > & operator+=(const SecBlock< T, A > &t)
Append contents from another SecBlock.
Definition: secblock.h:890
static const size_type ELEMS_MAX
Returns the maximum number of elements the allocator can provide.
Definition: secblock.h:57
void CleanGrow(size_type newSize)
Change size and preserve contents.
Definition: secblock.h:1007
const_iterator end() const
Provides a constant iterator pointing beyond the last element in the memory block.
Definition: secblock.h:778
void Assign(const SecBlock< T, A > &t)
Copy contents from another SecBlock.
Definition: secblock.h:863
SecBlock< T, A > operator+(const SecBlock< T, A > &t)
Construct a SecBlock from this and another SecBlock.
Definition: secblock.h:915
pointer allocate(size_type size, const void *hint)
Allocates a block of memory.
Definition: secblock.h:587
SecBlock(size_type size=0)
Construct a SecBlock with space for size elements.
Definition: secblock.h:717
Secure memory block with allocator and cleanup.
Definition: secblock.h:682
void memcpy_s(void *dest, size_t sizeInBytes, const void *src, size_t count)
Bounds checking replacement for memcpy()
Definition: misc.h:439
Library configuration file.
bool operator!=(const SecBlock< T, A > &t) const
Bitwise compare two SecBlocks.
Definition: secblock.h:946
STL namespace.
Common C++ header files.
void New(size_type newSize)
Change size without preserving contents.
Definition: secblock.h:959
SecBlock<byte> typedef.
Definition: secblock.h:1052
pointer allocate(size_type size, const void *hint)
Allocates a block of memory.
Definition: secblock.h:388
pointer reallocate(T *oldPtr, size_type oldSize, size_type newSize, bool preserve)
Reallocates a block of memory.
Definition: secblock.h:245
pointer reallocate(pointer oldPtr, size_type oldSize, size_type newSize, bool preserve)
Reallocates a block of memory.
Definition: secblock.h:442
bool operator==(const OID &lhs, const OID &rhs)
Compare two OIDs for equality.
Static secure memory block with cleanup.
Definition: secblock.h:322
Allocates a block of memory with cleanup.
Definition: secblock.h:173
size_type max_size() const
Returns the maximum number of elements the allocator can provide.
Definition: secblock.h:72
pointer allocate(size_type size)
Allocates a block of memory.
Definition: secblock.h:561
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:1343
bool IsAlignedOn(const void *ptr, unsigned int alignment)
Determines whether ptr is aligned to a minimum value.
Definition: misc.h:1085
pointer allocate(size_type size)
Allocates a block of memory.
Definition: secblock.h:362
void * UnalignedAllocate(size_t size)
Allocates a buffer.
Definition: misc.cpp:325
Template class memeber Rebind.
Definition: secblock.h:258
A::pointer data()
Provides a pointer to the first element in the memory block.
Definition: secblock.h:783
void Assign(const T *ptr, size_type len)
Set contents and size from an array.
Definition: secblock.h:835
FixedSizeAllocatorWithCleanup()
Constructs a FixedSizeAllocatorWithCleanup.
Definition: secblock.h:348
A::const_pointer data() const
Provides a pointer to the first element in the memory block.
Definition: secblock.h:786
Fixed size stack-based SecBlock with 16-byte alignment.
Definition: secblock.h:1083
void deallocate(void *ptr, size_type size)
Deallocates a block of memory.
Definition: secblock.h:407
pointer reallocate(pointer oldPtr, size_type oldSize, size_type newSize, bool preserve)
Reallocates a block of memory.
Definition: secblock.h:639
FixedSizeAllocatorWithCleanup()
Constructs a FixedSizeAllocatorWithCleanup.
Definition: secblock.h:547
SecBlock using AllocatorWithCleanup<byte, true> typedef.
Definition: secblock.h:1056
pointer allocate(size_type size, const void *ptr=NULL)
Allocates a block of memory.
Definition: secblock.h:193
Fixed size stack-based SecBlock.
Definition: secblock.h:1071
SecBlock(const SecBlock< T, A > &t)
Copy construct a SecBlock from another SecBlock.
Definition: secblock.h:723
void * memset_z(void *ptr, int value, size_t num)
Memory block initializer and eraser that attempts to survive optimizations.
Definition: misc.h:546
const T & STDMIN(const T &a, const T &b)
Replacement function for std::min.
Definition: misc.h:563
#define CRYPTOPP_ASSERT(exp)
Debugging and diagnostic assertion.
Definition: trap.h:60
void deallocate(void *ptr, size_type size)
Deallocates a block of memory.
Definition: secblock.h:217
iterator begin()
Provides an iterator pointing to the first element in the memory block.
Definition: secblock.h:766
bool operator==(const SecBlock< T, A > &t) const
Bitwise compare two SecBlocks.
Definition: secblock.h:933
NULL allocator.
Definition: secblock.h:284
SecBlockWithHint(size_t size)
construct a SecBlockWithHint with a count of elements
Definition: secblock.h:1096
const byte * BytePtr() const
Return a byte pointer to the first element in the memory block.
Definition: secblock.h:801
A::pointer StandardReallocate(A &alloc, T *oldPtr, typename A::size_type oldSize, typename A::size_type newSize, bool preserve)
Reallocation function.
Definition: secblock.h:142
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:100
const_iterator begin() const
Provides a constant iterator pointing to the first element in the memory block.
Definition: secblock.h:770
SecBlock(const T *ptr, size_type len)
Construct a SecBlock from an array of elements.
Definition: secblock.h:737
const T & STDMAX(const T &a, const T &b)
Replacement function for std::max.
Definition: misc.h:574
void deallocate(void *ptr, size_type size)
Deallocates a block of memory.
Definition: secblock.h:606
void Grow(size_type newSize)
Change size and preserve contents.
Definition: secblock.h:989
Crypto++ library namespace.
void destroy(V *ptr)
Destroys an V constructed with variadic arguments.
Definition: secblock.h:91
void Assign(size_type count, T value)
Set contents from a value.
Definition: secblock.h:848
void SetMark(size_t count)
Sets the number of elements to zeroize.
Definition: secblock.h:828
bool empty() const
Determines if the SecBlock is empty.
Definition: secblock.h:794
void UnalignedDeallocate(void *ptr)
Frees a buffer allocated with UnalignedAllocate.
Definition: misc.cpp:333
SecBlock<word> typedef.
Definition: secblock.h:1054
size_type size() const
Provides the count of elements in the SecBlock.
Definition: secblock.h:791
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:85
byte * BytePtr()
Provides a byte pointer to the first element in the memory block.
Definition: secblock.h:798