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