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