Crypto++ 7.0 Free C++ class library of cryptographic schemes

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