Crypto++ 8.2
Free C&
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
21NAMESPACE_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
27template<class T>
29{
30public:
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
101protected:
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 \
129typedef typename AllocatorBase<T>::value_type value_type;\
130typedef typename AllocatorBase<T>::size_type size_type;\
131typedef typename AllocatorBase<T>::difference_type difference_type;\
132typedef typename AllocatorBase<T>::pointer pointer;\
133typedef typename AllocatorBase<T>::const_pointer const_pointer;\
134typedef typename AllocatorBase<T>::reference reference;\
135typedef 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.
147template <class T, class A>
148typename 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.
178template <class T, bool T_Align16 = false>
180{
181public:
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
271CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup<byte>;
272CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup<word16>;
273CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup<word32>;
274CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup<word64>;
275#if defined(CRYPTOPP_WORD128_AVAILABLE)
276CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup<word128, true>; // for Integer
277#endif
278#if CRYPTOPP_BOOL_X86
279CRYPTOPP_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.
289template <class T>
291{
292public:
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.
327template <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.
347template <class T, size_t S, class A>
348class FixedSizeAllocatorWithCleanup<T, S, A, true> : public AllocatorBase<T>
349{
350public:
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
473private:
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.
546template <class T, size_t S, class A>
547class FixedSizeAllocatorWithCleanup<T, S, A, false> : public AllocatorBase<T>
548{
549public:
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
670private:
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
687template <class T, class A = AllocatorWithCleanup<T> >
689{
690public:
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
1050protected:
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.
1058class SecByteBlock : public SecBlock<byte> {};
1059/// \brief \ref SecBlock "SecBlock<word>" typedef.
1060class SecWordBlock : public SecBlock<word> {};
1061/// \brief SecBlock using \ref AllocatorWithCleanup "AllocatorWithCleanup<byte, true>" typedef
1062class 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
1076template <class T, unsigned int S, class A = FixedSizeAllocatorWithCleanup<T, S> >
1077class FixedSizeSecBlock : public SecBlock<T, A>
1078{
1079public:
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
1088template <class T, unsigned int S, bool T_Align16 = true>
1089class 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
1097template <class T, unsigned int S, class A = FixedSizeAllocatorWithCleanup<T, S, AllocatorWithCleanup<T> > >
1098class SecBlockWithHint : public SecBlock<T, A>
1099{
1100public:
1101 /// construct a SecBlockWithHint with a count of elements
1102 explicit SecBlockWithHint(size_t size) : SecBlock<T, A>(size) {}
1103};
1104
1105template<class T, bool A, class V, bool B>
1106inline bool operator==(const CryptoPP::AllocatorWithCleanup<T, A>&, const CryptoPP::AllocatorWithCleanup<V, B>&) {return (true);}
1107template<class T, bool A, class V, bool B>
1108inline bool operator!=(const CryptoPP::AllocatorWithCleanup<T, A>&, const CryptoPP::AllocatorWithCleanup<V, B>&) {return (false);}
1109
1110NAMESPACE_END
1111
1112NAMESPACE_BEGIN(std)
1113template <class T, class A>
1114inline 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
1121template <class _Tp1, class _Tp2>
1122inline CryptoPP::AllocatorWithCleanup<_Tp2>&
1123__stl_alloc_rebind(CryptoPP::AllocatorWithCleanup<_Tp1>& __a, const _Tp2*)
1124{
1125 return (CryptoPP::AllocatorWithCleanup<_Tp2>&)(__a);
1126}
1127#endif
1128
1129NAMESPACE_END
1130
1131#if CRYPTOPP_MSC_VERSION
1132# pragma warning(pop)
1133#endif
1134
1135#endif
bool operator==(const OID &lhs, const OID &rhs)
Compare two OIDs for equality.
bool operator!=(const OID &lhs, const OID &rhs)
Compare two OIDs for inequality.
SecBlock using AllocatorWithCleanup<byte, true> typedef.
Definition: secblock.h:1062
Base class for all allocators used by SecBlock.
Definition: secblock.h:29
void construct(V *ptr, Args &&... args)
Constructs a new V using variadic arguments.
Definition: secblock.h:90
static const size_type ELEMS_MAX
Returns the maximum number of elements the allocator can provide.
Definition: secblock.h:57
size_type max_size() const
Returns the maximum number of elements the allocator can provide.
Definition: secblock.h:72
void destroy(V *ptr)
Destroys an V constructed with variadic arguments.
Definition: secblock.h:97
Allocates a block of memory with cleanup.
Definition: secblock.h:180
pointer allocate(size_type size, const void *ptr=NULL)
Allocates a block of memory.
Definition: secblock.h:199
pointer reallocate(T *oldPtr, size_type oldSize, size_type newSize, bool preserve)
Reallocates a block of memory.
Definition: secblock.h:251
void deallocate(void *ptr, size_type size)
Deallocates a block of memory.
Definition: secblock.h:223
Fixed size stack-based SecBlock with 16-byte alignment.
Definition: secblock.h:1090
void deallocate(void *ptr, size_type size)
Deallocates a block of memory.
Definition: secblock.h:612
pointer allocate(size_type size)
Allocates a block of memory.
Definition: secblock.h:567
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
pointer allocate(size_type size, const void *hint)
Allocates a block of memory.
Definition: secblock.h:593
pointer reallocate(pointer oldPtr, size_type oldSize, size_type newSize, bool preserve)
Reallocates a block of memory.
Definition: secblock.h:448
pointer allocate(size_type size, const void *hint)
Allocates a block of memory.
Definition: secblock.h:394
FixedSizeAllocatorWithCleanup()
Constructs a FixedSizeAllocatorWithCleanup.
Definition: secblock.h:354
void deallocate(void *ptr, size_type size)
Deallocates a block of memory.
Definition: secblock.h:413
pointer allocate(size_type size)
Allocates a block of memory.
Definition: secblock.h:368
Static secure memory block with cleanup.
Definition: secblock.h:329
Fixed size stack-based SecBlock.
Definition: secblock.h:1078
FixedSizeSecBlock()
Construct a FixedSizeSecBlock.
Definition: secblock.h:1081
An invalid argument was detected.
Definition: cryptlib.h:203
NULL allocator.
Definition: secblock.h:291
Secure memory block with allocator and cleanup.
Definition: secblock.h:689
void Assign(size_type count, T value)
Set contents from a value.
Definition: secblock.h:854
iterator begin()
Provides an iterator pointing to the first element in the memory block.
Definition: secblock.h:772
const_iterator begin() const
Provides a constant iterator pointing to the first element in the memory block.
Definition: secblock.h:776
iterator end()
Provides an iterator pointing beyond the last element in the memory block.
Definition: secblock.h:780
SecBlock< T, A > operator+(const SecBlock< T, A > &t)
Construct a SecBlock from this and another SecBlock.
Definition: secblock.h:921
SecBlock(const SecBlock< T, A > &t)
Copy construct a SecBlock from another SecBlock.
Definition: secblock.h:729
void CleanNew(size_type newSize)
Change size without preserving contents.
Definition: secblock.h:980
void Assign(const SecBlock< T, A > &t)
Copy contents from another SecBlock.
Definition: secblock.h:869
void swap(SecBlock< T, A > &b)
Swap contents with another SecBlock.
Definition: secblock.h:1041
SecBlock(size_type size=0)
Construct a SecBlock with space for size elements.
Definition: secblock.h:723
A::pointer data()
Provides a pointer to the first element in the memory block.
Definition: secblock.h:789
void CleanGrow(size_type newSize)
Change size and preserve contents.
Definition: secblock.h:1013
bool operator!=(const SecBlock< T, A > &t) const
Bitwise compare two SecBlocks.
Definition: secblock.h:952
SecBlock(const T *ptr, size_type len)
Construct a SecBlock from an array of elements.
Definition: secblock.h:743
bool operator==(const SecBlock< T, A > &t) const
Bitwise compare two SecBlocks.
Definition: secblock.h:939
void Grow(size_type newSize)
Change size and preserve contents.
Definition: secblock.h:995
void New(size_type newSize)
Change size without preserving contents.
Definition: secblock.h:965
size_type SizeInBytes() const
Provides the number of bytes in the SecBlock.
Definition: secblock.h:811
void SetMark(size_t count)
Sets the number of elements to zeroize.
Definition: secblock.h:834
void Assign(const T *ptr, size_type len)
Set contents and size from an array.
Definition: secblock.h:841
byte * BytePtr()
Provides a byte pointer to the first element in the memory block.
Definition: secblock.h:804
const_iterator end() const
Provides a constant iterator pointing beyond the last element in the memory block.
Definition: secblock.h:784
A::const_pointer data() const
Provides a pointer to the first element in the memory block.
Definition: secblock.h:792
SecBlock< T, A > & operator+=(const SecBlock< T, A > &t)
Append contents from another SecBlock.
Definition: secblock.h:896
bool empty() const
Determines if the SecBlock is empty.
Definition: secblock.h:800
const byte * BytePtr() const
Return a byte pointer to the first element in the memory block.
Definition: secblock.h:807
SecBlock< T, A > & operator=(const SecBlock< T, A > &t)
Assign contents from another SecBlock.
Definition: secblock.h:886
size_type size() const
Provides the count of elements in the SecBlock.
Definition: secblock.h:797
void resize(size_type newSize)
Change size and preserve contents.
Definition: secblock.h:1031
Stack-based SecBlock that grows into the heap.
Definition: secblock.h:1099
SecBlockWithHint(size_t size)
construct a SecBlockWithHint with a count of elements
Definition: secblock.h:1102
SecBlock<byte> typedef.
Definition: secblock.h:1058
SecBlock<word> typedef.
Definition: secblock.h:1060
Library configuration file.
Utility functions for the Crypto++ library.
const T & STDMAX(const T &a, const T &b)
Replacement function for std::max.
Definition: misc.h:578
#define SIZE_MAX
The maximum value of a machine word.
Definition: misc.h:86
void SecureWipeArray(T *buf, size_t n)
Sets each element of an array to 0.
Definition: misc.h:1402
void memcpy_s(void *dest, size_t sizeInBytes, const void *src, size_t count)
Bounds checking replacement for memcpy()
Definition: misc.h:443
const T & STDMIN(const T &a, const T &b)
Replacement function for std::min.
Definition: misc.h:567
bool IsAlignedOn(const void *ptr, unsigned int alignment)
Determines whether ptr is aligned to a minimum value.
Definition: misc.h:1143
void * memset_z(void *ptr, int value, size_t num)
Memory block initializer and eraser that attempts to survive optimizations.
Definition: misc.h:550
Crypto++ library namespace.
A::pointer StandardReallocate(A &alloc, T *oldPtr, typename A::size_type oldSize, typename A::size_type newSize, bool preserve)
Reallocation function.
Definition: secblock.h:148
Common C++ header files.
Template class member Rebind.
Definition: secblock.h:264
#define CRYPTOPP_ASSERT(exp)
Debugging and diagnostic assertion.
Definition: trap.h:69