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