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