Security Scol plugin
secblock.h
Go to the documentation of this file.
1// secblock.h - originally written and placed in the public domain by Wei Dai
2
5
6#ifndef CRYPTOPP_SECBLOCK_H
7#define CRYPTOPP_SECBLOCK_H
8
9#include "config.h"
10#include "allocate.h"
11#include "misc.h"
12#include "stdcpp.h"
13
14#if CRYPTOPP_MSC_VERSION
15# pragma warning(push)
16# pragma warning(disable: 4231 4275 4700)
17# if (CRYPTOPP_MSC_VERSION >= 1400)
18# pragma warning(disable: 6011 6386 28193)
19# endif
20#endif
21
22NAMESPACE_BEGIN(CryptoPP)
23
24// ************** secure memory allocation ***************
25
26
28template<class T>
30{
31public:
32 typedef T value_type;
33 typedef size_t size_type;
34 typedef std::ptrdiff_t difference_type;
35 typedef T * pointer;
36 typedef const T * const_pointer;
37 typedef T & reference;
38 typedef const T & const_reference;
39
40 pointer address(reference r) const {return (&r);}
41 const_pointer address(const_reference r) const {return (&r); }
42 void construct(pointer p, const T& val) {new (p) T(val);}
43 void destroy(pointer p) {CRYPTOPP_UNUSED(p); p->~T();}
44
57#if defined(CRYPTOPP_DOXYGEN_PROCESSING)
58 static const size_type ELEMS_MAX = ...;
59#elif defined(_MSC_VER) && (_MSC_VER <= 1400)
60 static const size_type ELEMS_MAX = (~(size_type)0)/sizeof(T);
61#elif defined(CRYPTOPP_CXX11_STRONG_ENUM)
62 enum : size_type {ELEMS_MAX = SIZE_MAX/sizeof(T)};
63#else
64 static const size_type ELEMS_MAX = SIZE_MAX/sizeof(T);
65#endif
66
73 CRYPTOPP_CONSTEXPR size_type max_size() const {return ELEMS_MAX;}
74
75#if defined(__SUNPRO_CC)
76 // https://github.com/weidai11/cryptopp/issues/770
77 // and https://stackoverflow.com/q/53999461/608639
78 CRYPTOPP_CONSTEXPR size_type max_size(size_type n) const {return SIZE_MAX/n;}
79#endif
80
81#if defined(CRYPTOPP_CXX11_VARIADIC_TEMPLATES) || defined(CRYPTOPP_DOXYGEN_PROCESSING)
82
90 template<typename V, typename... Args>
91 void construct(V* ptr, Args&&... args) {::new ((void*)ptr) V(std::forward<Args>(args)...);}
92
97 template<typename V>
98 void destroy(V* ptr) {if (ptr) ptr->~V();}
99
100#endif
101
102protected:
103
119 static void CheckSize(size_t size)
120 {
121 // Squash MSC C4100 warning for size. Also see commit 42b7c4ea5673.
122 CRYPTOPP_UNUSED(size);
123 // C++ throws std::bad_alloc (C++03) or std::bad_array_new_length (C++11) here.
124 if (sizeof(T) != 1 && size > ELEMS_MAX)
125 throw InvalidArgument("AllocatorBase: requested size would cause integer overflow");
126 }
127};
128
129#define CRYPTOPP_INHERIT_ALLOCATOR_TYPES(T_type) \
130 typedef typename AllocatorBase<T_type>::value_type value_type;\
131 typedef typename AllocatorBase<T_type>::size_type size_type;\
132 typedef typename AllocatorBase<T_type>::difference_type difference_type;\
133 typedef typename AllocatorBase<T_type>::pointer pointer;\
134 typedef typename AllocatorBase<T_type>::const_pointer const_pointer;\
135 typedef typename AllocatorBase<T_type>::reference reference;\
136 typedef typename AllocatorBase<T_type>::const_reference const_reference;
137
148template <class T, class A>
149typename A::pointer StandardReallocate(A& alloc, T *oldPtr, typename A::size_type oldSize, typename A::size_type newSize, bool preserve)
150{
151 // Avoid assert on pointer in reallocate. SecBlock regularly uses NULL
152 // pointers rather returning non-NULL 0-sized pointers.
153 if (oldSize == newSize)
154 return oldPtr;
155
156 if (preserve)
157 {
158 typename A::pointer newPtr = alloc.allocate(newSize, NULLPTR);
159 const typename A::size_type copySize = STDMIN(oldSize, newSize) * sizeof(T);
160
161 if (oldPtr && newPtr)
162 memcpy_s(newPtr, copySize, oldPtr, copySize);
163
164 if (oldPtr)
165 alloc.deallocate(oldPtr, oldSize);
166
167 return newPtr;
168 }
169 else
170 {
171 if (oldPtr)
172 alloc.deallocate(oldPtr, oldSize);
173
174 return alloc.allocate(newSize, NULLPTR);
175 }
176}
177
186template <class T, bool T_Align16 = false>
188{
189public:
190 CRYPTOPP_INHERIT_ALLOCATOR_TYPES(T)
191
192
206 pointer allocate(size_type size, const void *ptr = NULLPTR)
207 {
208 CRYPTOPP_UNUSED(ptr); CRYPTOPP_ASSERT(ptr == NULLPTR);
209 this->CheckSize(size);
210 if (size == 0)
211 return NULLPTR;
212
213#if CRYPTOPP_BOOL_ALIGN16
214 if (T_Align16)
215 return reinterpret_cast<pointer>(AlignedAllocate(size*sizeof(T)));
216#endif
217
218 return reinterpret_cast<pointer>(UnalignedAllocate(size*sizeof(T)));
219 }
220
229 void deallocate(void *ptr, size_type size)
230 {
231 // Avoid assert on pointer in deallocate. SecBlock regularly uses NULL
232 // pointers rather returning non-NULL 0-sized pointers.
233 if (ptr)
234 {
235 SecureWipeArray(reinterpret_cast<pointer>(ptr), size);
236
237#if CRYPTOPP_BOOL_ALIGN16
238 if (T_Align16)
239 return AlignedDeallocate(ptr);
240#endif
241
242 UnalignedDeallocate(ptr);
243 }
244 }
245
259 pointer reallocate(T *oldPtr, size_type oldSize, size_type newSize, bool preserve)
260 {
261 CRYPTOPP_ASSERT((oldPtr && oldSize) || !(oldPtr || oldSize));
262 return StandardReallocate(*this, oldPtr, oldSize, newSize, preserve);
263 }
264
272 template <class V> struct rebind { typedef AllocatorWithCleanup<V, T_Align16> other; };
273#if _MSC_VER >= 1500
275 template <class V, bool A> AllocatorWithCleanup(const AllocatorWithCleanup<V, A> &) {}
276#endif
277};
278
279CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup<byte>;
280CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup<word16>;
281CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup<word32>;
282CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup<word64>;
283#if defined(CRYPTOPP_WORD128_AVAILABLE)
284CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup<word128, true>; // for Integer
285#endif
286#if CRYPTOPP_BOOL_X86
287CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup<word, true>; // for Integer
288#endif
289
297template <class T>
299{
300public:
301 //LCOV_EXCL_START
302 CRYPTOPP_INHERIT_ALLOCATOR_TYPES(T)
303
304 // TODO: should this return NULL or throw bad_alloc? Non-Windows C++ standard
305 // libraries always throw. And late mode Windows throws. Early model Windows
306 // (circa VC++ 6.0) returned NULL.
307 pointer allocate(size_type n, const void* unused = NULLPTR)
308 {
309 CRYPTOPP_UNUSED(n); CRYPTOPP_UNUSED(unused);
310 CRYPTOPP_ASSERT(false); return NULLPTR;
311 }
312
313 void deallocate(void *p, size_type n)
314 {
315 CRYPTOPP_UNUSED(p); CRYPTOPP_UNUSED(n);
316 CRYPTOPP_ASSERT(false);
317 }
318
319 CRYPTOPP_CONSTEXPR size_type max_size() const {return 0;}
320 //LCOV_EXCL_STOP
321};
322
335template <class T, size_t S, class A = NullAllocator<T>, bool T_Align16 = false>
337{
338 // The body of FixedSizeAllocatorWithCleanup is provided in the two
339 // partial specializations that follow. The two specializations
340 // pivot on the boolean template parameter T_Align16.
341};
342
353template <class T, size_t S, class A>
354class FixedSizeAllocatorWithCleanup<T, S, A, true> : public AllocatorBase<T>
355{
356public:
357 CRYPTOPP_INHERIT_ALLOCATOR_TYPES(T)
358
359
360 FixedSizeAllocatorWithCleanup() : m_allocated(false) {}
361
374 pointer allocate(size_type size)
375 {
376 CRYPTOPP_ASSERT(IsAlignedOn(m_array, 8));
377
378 if (size <= S && !m_allocated)
379 {
380 m_allocated = true;
381 return GetAlignedArray();
382 }
383 else
384 return m_fallbackAllocator.allocate(size);
385 }
386
400 pointer allocate(size_type size, const void *hint)
401 {
402 CRYPTOPP_ASSERT(IsAlignedOn(m_array, 8));
403
404 if (size <= S && !m_allocated)
405 {
406 m_allocated = true;
407 return GetAlignedArray();
408 }
409 else
410 return m_fallbackAllocator.allocate(size, hint);
411 }
412
421 void deallocate(void *ptr, size_type size)
422 {
423 // Avoid assert on pointer in deallocate. SecBlock regularly uses NULL
424 // pointers rather returning non-NULL 0-sized pointers.
425 if (ptr == GetAlignedArray())
426 {
427 // If the m_allocated assert fires then the bit twiddling for
428 // GetAlignedArray() is probably incorrect for the platform.
429 // Be sure to check CRYPTOPP_ALIGN_DATA(8). The platform may
430 // not have a way to declaratively align data to 8.
431 CRYPTOPP_ASSERT(size <= S);
432 CRYPTOPP_ASSERT(m_allocated);
433 m_allocated = false;
434 SecureWipeArray(reinterpret_cast<pointer>(ptr), size);
435 }
436 else
437 {
438 if (ptr)
439 m_fallbackAllocator.deallocate(ptr, size);
440 }
441 }
442
461 pointer reallocate(pointer oldPtr, size_type oldSize, size_type newSize, bool preserve)
462 {
463 if (oldPtr == GetAlignedArray() && newSize <= S)
464 {
465 CRYPTOPP_ASSERT(oldSize <= S);
466 if (oldSize > newSize)
467 SecureWipeArray(oldPtr+newSize, oldSize-newSize);
468 return oldPtr;
469 }
470
471 pointer newPtr = allocate(newSize, NULLPTR);
472 if (preserve && newSize)
473 {
474 const size_type copySize = STDMIN(oldSize, newSize);
475 if (newPtr && oldPtr) // GCC analyzer warning
476 memcpy_s(newPtr, sizeof(T)*newSize, oldPtr, sizeof(T)*copySize);
477 }
478 deallocate(oldPtr, oldSize);
479 return newPtr;
480 }
481
482 CRYPTOPP_CONSTEXPR size_type max_size() const
483 {
484 return STDMAX(m_fallbackAllocator.max_size(), S);
485 }
486
487private:
488
489#if CRYPTOPP_BOOL_ALIGN16
490
491 // There be demons here... We cannot use CRYPTOPP_ALIGN_DATA(16)
492 // because linkers on 32-bit machines and some 64-bit machines
493 // align the stack to 8-bytes or less, and not 16-bytes as
494 // requested. We can only count on a smaller alignment. All
495 // toolchains tested appear to honor CRYPTOPP_ALIGN_DATA(8). Also
496 // see http://stackoverflow.com/a/1468656/608639.
497 //
498 // The 16-byte alignment is achieved by padding the requested
499 // size with extra elements so we have at least 8-bytes of slack
500 // to work with. Then the array pointer is moved to achieve a
501 // 16-byte alignment.
502 //
503 // The additional 8-bytes introduces a small secondary issue.
504 // The secondary issue is, a large T results in 0 = 8/sizeof(T).
505 // The library is OK but users may hit it. So we need to guard
506 // for a large T, and that is what the enum and PAD achieves.
507 T* GetAlignedArray() {
508
509 // m_array is aligned on 8 byte boundaries due to
510 // CRYPTOPP_ALIGN_DATA(8). If m_array%16 is 0, then the buffer
511 // is 16-byte aligned and nothing needs to be done. if
512 // m_array%16 is 8, then the buffer is not 16-byte aligned and
513 // we need to add 8. 8 has that nice symmetric property.
514 //
515 // If we needed to use CRYPTOPP_ALIGN_DATA(4) due to toolchain
516 // limitations, then the calculation would be slightly more
517 // costly: ptr = m_array + (16 - (m_array % 16)) % 16;
518 CRYPTOPP_ASSERT(IsAlignedOn(m_array, 8));
519 int off = reinterpret_cast<uintptr_t>(m_array) % 16;
520 byte* ptr = reinterpret_cast<byte*>(m_array) + off;
521
522 // Verify the 16-byte alignment. This is the point
523 // of these extra gyrations.
524 CRYPTOPP_ASSERT(IsAlignedOn(ptr, 16));
525 // Verify the lower bound. This is Issue 982/988.
526 CRYPTOPP_ASSERT(
527 reinterpret_cast<uintptr_t>(ptr) >=
528 reinterpret_cast<uintptr_t>(m_array)
529 );
530 // Verify the upper bound. Allocated array with
531 // pad is large enough.
532 CRYPTOPP_ASSERT(
533 reinterpret_cast<uintptr_t>(ptr+S*sizeof(T)) <=
534 reinterpret_cast<uintptr_t>(m_array+(S+PAD))
535 );
536
537 // void* to silence Clang warnings
538 return reinterpret_cast<T*>(
539 static_cast<void*>(ptr)
540 );
541 }
542
543 // PAD is elements, not bytes, and rounded up to ensure no overflow.
544 enum { Q = sizeof(T), PAD = (Q >= 8) ? 1 : (Q >= 4) ? 2 : (Q >= 2) ? 4 : 8 };
545 // enum { Q = sizeof(T), PAD = (Q >= 16) ? 1 : (Q >= 8) ? 2 : (Q >= 4) ? 4 : (Q >= 2) ? 8 : 16 };
546 CRYPTOPP_ALIGN_DATA(8) T m_array[S+PAD];
547
548#else
549
550 // CRYPTOPP_BOOL_ALIGN16 is 0. If we are here then the user
551 // probably compiled with CRYPTOPP_DISABLE_ASM. Normally we
552 // would use the natural alignment of T. The problem we are
553 // having is, some toolchains are changing the boundary for
554 // 64-bit arrays. 64-bit elements require 8-byte alignment,
555 // but the toolchain is laying the array out on a 4 byte
556 // boundary. See GH #992 for mystery alignment,
557 // https://github.com/weidai11/cryptopp/issues/992
558 T* GetAlignedArray() {return m_array;}
559 CRYPTOPP_ALIGN_DATA(8) T m_array[S];
560
561#endif
562
563 A m_fallbackAllocator;
564 bool m_allocated;
565};
566
577template <class T, size_t S, class A>
578class FixedSizeAllocatorWithCleanup<T, S, A, false> : public AllocatorBase<T>
579{
580public:
581 CRYPTOPP_INHERIT_ALLOCATOR_TYPES(T)
582
583
584 FixedSizeAllocatorWithCleanup() : m_allocated(false) {}
585
598 pointer allocate(size_type size)
599 {
600 CRYPTOPP_ASSERT(IsAlignedOn(m_array, 8));
601
602 if (size <= S && !m_allocated)
603 {
604 m_allocated = true;
605 return GetAlignedArray();
606 }
607 else
608 return m_fallbackAllocator.allocate(size);
609 }
610
624 pointer allocate(size_type size, const void *hint)
625 {
626 if (size <= S && !m_allocated)
627 {
628 m_allocated = true;
629 return GetAlignedArray();
630 }
631 else
632 return m_fallbackAllocator.allocate(size, hint);
633 }
634
643 void deallocate(void *ptr, size_type size)
644 {
645 // Avoid assert on pointer in deallocate. SecBlock regularly uses NULL
646 // pointers rather returning non-NULL 0-sized pointers.
647 if (ptr == GetAlignedArray())
648 {
649 // If the m_allocated assert fires then
650 // something overwrote the flag.
651 CRYPTOPP_ASSERT(size <= S);
652 CRYPTOPP_ASSERT(m_allocated);
653 m_allocated = false;
654 SecureWipeArray((pointer)ptr, size);
655 }
656 else
657 {
658 if (ptr)
659 m_fallbackAllocator.deallocate(ptr, size);
660 m_allocated = false;
661 }
662 }
663
682 pointer reallocate(pointer oldPtr, size_type oldSize, size_type newSize, bool preserve)
683 {
684 if (oldPtr == GetAlignedArray() && newSize <= S)
685 {
686 CRYPTOPP_ASSERT(oldSize <= S);
687 if (oldSize > newSize)
688 SecureWipeArray(oldPtr+newSize, oldSize-newSize);
689 return oldPtr;
690 }
691
692 pointer newPtr = allocate(newSize, NULLPTR);
693 if (preserve && newSize)
694 {
695 const size_type copySize = STDMIN(oldSize, newSize);
696 if (newPtr && oldPtr) // GCC analyzer warning
697 memcpy_s(newPtr, sizeof(T)*newSize, oldPtr, sizeof(T)*copySize);
698 }
699 deallocate(oldPtr, oldSize);
700 return newPtr;
701 }
702
703 CRYPTOPP_CONSTEXPR size_type max_size() const
704 {
705 return STDMAX(m_fallbackAllocator.max_size(), S);
706 }
707
708private:
709
710 // T_Align16 is false. Normally we would use the natural
711 // alignment of T. The problem we are having is, some toolchains
712 // are changing the boundary for 64-bit arrays. 64-bit elements
713 // require 8-byte alignment, but the toolchain is laying the array
714 // out on a 4 byte boundary. See GH #992 for mystery alignment,
715 // https://github.com/weidai11/cryptopp/issues/992
716 T* GetAlignedArray() {return m_array;}
717 CRYPTOPP_ALIGN_DATA(8) T m_array[S];
718
719 A m_fallbackAllocator;
720 bool m_allocated;
721};
722
729template <class T, class A = AllocatorWithCleanup<T> >
731{
732public:
733 typedef typename A::value_type value_type;
734 typedef typename A::pointer iterator;
735 typedef typename A::const_pointer const_iterator;
736 typedef typename A::size_type size_type;
737
750#if defined(CRYPTOPP_DOXYGEN_PROCESSING)
751 static const size_type ELEMS_MAX = ...;
752#elif defined(_MSC_VER) && (_MSC_VER <= 1400)
753 static const size_type ELEMS_MAX = (~(size_type)0)/sizeof(T);
754#elif defined(CRYPTOPP_CXX11_STRONG_ENUM)
755 enum : size_type {ELEMS_MAX = A::ELEMS_MAX};
756#else
757 static const size_type ELEMS_MAX = SIZE_MAX/sizeof(T);
758#endif
759
766 explicit SecBlock(size_type size=0)
767 : m_mark(ELEMS_MAX), m_size(size), m_ptr(m_alloc.allocate(size, NULLPTR)) { }
768
774 : m_mark(t.m_mark), m_size(t.m_size), m_ptr(m_alloc.allocate(t.m_size, NULLPTR)) {
775 CRYPTOPP_ASSERT((!t.m_ptr && !m_size) || (t.m_ptr && m_size));
776 if (m_ptr && t.m_ptr)
777 memcpy_s(m_ptr, m_size*sizeof(T), t.m_ptr, t.m_size*sizeof(T));
778 }
779
789 SecBlock(const T *ptr, size_type len)
790 : m_mark(ELEMS_MAX), m_size(len), m_ptr(m_alloc.allocate(len, NULLPTR)) {
791 CRYPTOPP_ASSERT((!m_ptr && !m_size) || (m_ptr && m_size));
792 if (m_ptr && ptr)
793 memcpy_s(m_ptr, m_size*sizeof(T), ptr, len*sizeof(T));
794 else if (m_ptr && m_size)
795 memset(m_ptr, 0, m_size*sizeof(T));
796 }
797
798 ~SecBlock()
799 {m_alloc.deallocate(m_ptr, STDMIN(m_size, m_mark));}
800
801#ifdef __BORLANDC__
805 operator T *() const
806 {return (T*)m_ptr;}
807#else
811 operator const void *() const
812 {return m_ptr;}
813
817 operator void *()
818 {return m_ptr;}
819
823 operator const T *() const
824 {return m_ptr;}
825
829 operator T *()
830 {return m_ptr;}
831#endif
832
836 iterator begin()
837 {return m_ptr;}
841 const_iterator begin() const
842 {return m_ptr;}
846 iterator end()
847 {return m_ptr+m_size;}
851 const_iterator end() const
852 {return m_ptr+m_size;}
853
857 typename A::pointer data() {return m_ptr;}
861 typename A::const_pointer data() const {return m_ptr;}
862
867 size_type size() const {return m_size;}
871 bool empty() const {return m_size == 0;}
872
876 byte * BytePtr() {return (byte *)m_ptr;}
880 const byte * BytePtr() const {return (const byte *)m_ptr;}
885 size_type SizeInBytes() const {return m_size*sizeof(T);}
886
898 void Assign(const T *ptr, size_type len)
899 {
900 New(len);
901 if (m_ptr && ptr) // GCC analyzer warning
902 memcpy_s(m_ptr, m_size*sizeof(T), ptr, len*sizeof(T));
903 m_mark = ELEMS_MAX;
904 }
905
913 void Assign(size_type count, T value)
914 {
915 New(count);
916 for (size_t i=0; i<count; ++i)
917 m_ptr[i] = value;
918 m_mark = ELEMS_MAX;
919 }
920
928 void Assign(const SecBlock<T, A> &t)
929 {
930 if (this != &t)
931 {
932 New(t.m_size);
933 if (m_ptr && t.m_ptr) // GCC analyzer warning
934 memcpy_s(m_ptr, m_size*sizeof(T), t, t.m_size*sizeof(T));
935 }
936 m_mark = ELEMS_MAX;
937 }
938
952 void Append(const T *ptr, size_type len)
953 {
954 if (ELEMS_MAX - m_size < len)
955 throw InvalidArgument("SecBlock: buffer overflow");
956
957 const size_type oldSize = m_size;
958 Grow(m_size+len);
959 if (m_ptr && ptr) // GCC analyzer warning
960 memcpy_s(m_ptr+oldSize, (m_size-oldSize)*sizeof(T), ptr, len*sizeof(T));
961 m_mark = ELEMS_MAX;
962 }
963
973 void Append(const SecBlock<T, A> &t)
974 {
975 if (ELEMS_MAX - m_size < t.m_size)
976 throw InvalidArgument("SecBlock: buffer overflow");
977
978 const size_type oldSize = m_size;
979 if (this != &t) // s += t
980 {
981 Grow(m_size+t.m_size);
982 if (m_ptr && t.m_ptr) // GCC analyzer warning
983 memcpy_s(m_ptr+oldSize, (m_size-oldSize)*sizeof(T), t.m_ptr, t.m_size*sizeof(T));
984 }
985 else // t += t
986 {
987 Grow(m_size*2);
988 if (m_ptr) // GCC analyzer warning
989 memmove_s(m_ptr+oldSize, (m_size-oldSize)*sizeof(T), m_ptr, oldSize*sizeof(T));
990 }
991 m_mark = ELEMS_MAX;
992 }
993
1004 void Append(size_type count, T value)
1005 {
1006 if (ELEMS_MAX - m_size < count)
1007 throw InvalidArgument("SecBlock: buffer overflow");
1008
1009 const size_type oldSize = m_size;
1010 Grow(m_size+count);
1011 for (size_t i=oldSize; i<oldSize+count; ++i)
1012 m_ptr[i] = value;
1013 m_mark = ELEMS_MAX;
1014 }
1015
1037 void SetMark(size_t count) {m_mark = count;}
1038
1048 {
1049 // Assign guards for self-assignment
1050 Assign(t);
1051 return *this;
1052 }
1053
1060 {
1061 // Append guards for overflow
1062 Append(t);
1063 return *this;
1064 }
1065
1074 {
1075 CRYPTOPP_ASSERT((!m_ptr && !m_size) || (m_ptr && m_size));
1076 CRYPTOPP_ASSERT((!t.m_ptr && !t.m_size) || (t.m_ptr && t.m_size));
1077 if(!t.m_size) return SecBlock(*this);
1078
1079 SecBlock<T, A> result(m_size+t.m_size);
1080 if (m_size)
1081 memcpy_s(result.m_ptr, result.m_size*sizeof(T), m_ptr, m_size*sizeof(T));
1082 if (result.m_ptr && t.m_ptr) // GCC analyzer warning
1083 memcpy_s(result.m_ptr+m_size, (result.m_size-m_size)*sizeof(T), t.m_ptr, t.m_size*sizeof(T));
1084 return result;
1085 }
1086
1095 bool operator==(const SecBlock<T, A> &t) const
1096 {
1097 return m_size == t.m_size && VerifyBufsEqual(
1098 reinterpret_cast<const byte*>(m_ptr),
1099 reinterpret_cast<const byte*>(t.m_ptr), m_size*sizeof(T));
1100 }
1101
1111 bool operator!=(const SecBlock<T, A> &t) const
1112 {
1113 return !operator==(t);
1114 }
1115
1126 void New(size_type newSize)
1127 {
1128 m_ptr = m_alloc.reallocate(m_ptr, m_size, newSize, false);
1129 m_size = newSize;
1130 m_mark = ELEMS_MAX;
1131 }
1132
1143 void CleanNew(size_type newSize)
1144 {
1145 New(newSize);
1146 if (m_ptr) {memset_z(m_ptr, 0, m_size*sizeof(T));}
1147 m_mark = ELEMS_MAX;
1148 }
1149
1160 void Grow(size_type newSize)
1161 {
1162 if (newSize > m_size)
1163 {
1164 m_ptr = m_alloc.reallocate(m_ptr, m_size, newSize, true);
1165 m_size = newSize;
1166 }
1167 m_mark = ELEMS_MAX;
1168 }
1169
1179 void CleanGrow(size_type newSize)
1180 {
1181 if (newSize > m_size)
1182 {
1183 m_ptr = m_alloc.reallocate(m_ptr, m_size, newSize, true);
1184 memset_z(m_ptr+m_size, 0, (newSize-m_size)*sizeof(T));
1185 m_size = newSize;
1186 }
1187 m_mark = ELEMS_MAX;
1188 }
1189
1198 void resize(size_type newSize)
1199 {
1200 m_ptr = m_alloc.reallocate(m_ptr, m_size, newSize, true);
1201 m_size = newSize;
1202 m_mark = ELEMS_MAX;
1203 }
1204
1210 {
1211 // Swap must occur on the allocator in case its FixedSize that spilled into the heap.
1212 std::swap(m_alloc, b.m_alloc);
1213 std::swap(m_mark, b.m_mark);
1214 std::swap(m_size, b.m_size);
1215 std::swap(m_ptr, b.m_ptr);
1216 }
1217
1218protected:
1219 A m_alloc;
1220 size_type m_mark, m_size;
1221 T *m_ptr;
1222};
1223
1224#ifdef CRYPTOPP_DOXYGEN_PROCESSING
1226class SecByteBlock : public SecBlock<byte> {};
1228class SecWordBlock : public SecBlock<word> {};
1230class AlignedSecByteBlock : public SecBlock<byte, AllocatorWithCleanup<byte, true> > {};
1231#else
1235#endif
1236
1237// No need for move semantics on derived class *if* the class does not add any
1238// data members; see http://stackoverflow.com/q/31755703, and Rule of {0|3|5}.
1239
1244template <class T, unsigned int S, class A = FixedSizeAllocatorWithCleanup<T, S> >
1245class FixedSizeSecBlock : public SecBlock<T, A>
1246{
1247public:
1249 explicit FixedSizeSecBlock() : SecBlock<T, A>(S) {}
1250};
1251
1257template <class T, unsigned int S, bool T_Align16 = true>
1258class FixedSizeAlignedSecBlock : public FixedSizeSecBlock<T, S, FixedSizeAllocatorWithCleanup<T, S, NullAllocator<T>, T_Align16> >
1259{
1260};
1261
1266template <class T, unsigned int S, class A = FixedSizeAllocatorWithCleanup<T, S, AllocatorWithCleanup<T> > >
1267class SecBlockWithHint : public SecBlock<T, A>
1268{
1269public:
1271 explicit SecBlockWithHint(size_t size) : SecBlock<T, A>(size) {}
1272};
1273
1274template<class T, bool A, class V, bool B>
1275inline bool operator==(const CryptoPP::AllocatorWithCleanup<T, A>&, const CryptoPP::AllocatorWithCleanup<V, B>&) {return (true);}
1276template<class T, bool A, class V, bool B>
1277inline bool operator!=(const CryptoPP::AllocatorWithCleanup<T, A>&, const CryptoPP::AllocatorWithCleanup<V, B>&) {return (false);}
1278
1279NAMESPACE_END
1280
1281NAMESPACE_BEGIN(std)
1282
1283
1288template <class T, class A>
1289inline void swap(CryptoPP::SecBlock<T, A> &a, CryptoPP::SecBlock<T, A> &b)
1290{
1291 a.swap(b);
1292}
1293
1294#if defined(_STLP_DONT_SUPPORT_REBIND_MEMBER_TEMPLATE) || (defined(_STLPORT_VERSION) && !defined(_STLP_MEMBER_TEMPLATE_CLASSES))
1295// working for STLport 5.1.3 and MSVC 6 SP5
1296template <class _Tp1, class _Tp2>
1297inline CryptoPP::AllocatorWithCleanup<_Tp2>&
1298__stl_alloc_rebind(CryptoPP::AllocatorWithCleanup<_Tp1>& __a, const _Tp2*)
1299{
1300 return (CryptoPP::AllocatorWithCleanup<_Tp2>&)(__a);
1301}
1302#endif
1303
1304NAMESPACE_END
1305
1306#if CRYPTOPP_MSC_VERSION
1307# pragma warning(pop)
1308#endif
1309
1310#endif
Functions for allocating aligned buffers.
Base class for all allocators used by SecBlock.
Definition secblock.h:30
static const size_type ELEMS_MAX
Returns the maximum number of elements the allocator can provide.
Definition secblock.h:64
static void CheckSize(size_t size)
Verifies the allocator can satisfy a request based on size.
Definition secblock.h:119
CRYPTOPP_CONSTEXPR size_type max_size() const
Returns the maximum number of elements the allocator can provide.
Definition secblock.h:73
Allocates a block of memory with cleanup.
Definition secblock.h:188
pointer allocate(size_type size, const void *ptr=NULLPTR)
Allocates a block of memory.
Definition secblock.h:206
pointer reallocate(T *oldPtr, size_type oldSize, size_type newSize, bool preserve)
Reallocates a block of memory.
Definition secblock.h:259
void deallocate(void *ptr, size_type size)
Deallocates a block of memory.
Definition secblock.h:229
Fixed size stack-based SecBlock with 16-byte alignment.
Definition secblock.h:1259
void deallocate(void *ptr, size_type size)
Deallocates a block of memory.
Definition secblock.h:643
pointer allocate(size_type size)
Allocates a block of memory.
Definition secblock.h:598
pointer reallocate(pointer oldPtr, size_type oldSize, size_type newSize, bool preserve)
Reallocates a block of memory.
Definition secblock.h:682
pointer allocate(size_type size, const void *hint)
Allocates a block of memory.
Definition secblock.h:624
pointer reallocate(pointer oldPtr, size_type oldSize, size_type newSize, bool preserve)
Reallocates a block of memory.
Definition secblock.h:461
pointer allocate(size_type size, const void *hint)
Allocates a block of memory.
Definition secblock.h:400
void deallocate(void *ptr, size_type size)
Deallocates a block of memory.
Definition secblock.h:421
pointer allocate(size_type size)
Allocates a block of memory.
Definition secblock.h:374
Static secure memory block with cleanup.
Definition secblock.h:337
Fixed size stack-based SecBlock.
Definition secblock.h:1246
FixedSizeSecBlock()
Construct a FixedSizeSecBlock.
Definition secblock.h:1249
An invalid argument was detected.
Definition cryptlib.h:203
NULL allocator.
Definition secblock.h:299
Secure memory block with allocator and cleanup.
Definition secblock.h:731
void Assign(size_type count, T value)
Set contents from a value.
Definition secblock.h:913
iterator begin()
Provides an iterator pointing to the first element in the memory block.
Definition secblock.h:836
const_iterator begin() const
Provides a constant iterator pointing to the first element in the memory block.
Definition secblock.h:841
void Append(const T *ptr, size_type len)
Append contents from an array.
Definition secblock.h:952
iterator end()
Provides an iterator pointing beyond the last element in the memory block.
Definition secblock.h:846
SecBlock< T, A > operator+(const SecBlock< T, A > &t)
Construct a SecBlock from this and another SecBlock.
Definition secblock.h:1073
SecBlock(const SecBlock< T, A > &t)
Copy construct a SecBlock from another SecBlock.
Definition secblock.h:773
void CleanNew(size_type newSize)
Change size without preserving contents.
Definition secblock.h:1143
void Assign(const SecBlock< T, A > &t)
Copy contents from another SecBlock.
Definition secblock.h:928
void swap(SecBlock< T, A > &b)
Swap contents with another SecBlock.
Definition secblock.h:1209
SecBlock(size_type size=0)
Construct a SecBlock with space for size elements.
Definition secblock.h:766
A::pointer data()
Provides a pointer to the first element in the memory block.
Definition secblock.h:857
void CleanGrow(size_type newSize)
Change size and preserve contents.
Definition secblock.h:1179
bool operator!=(const SecBlock< T, A > &t) const
Bitwise compare two SecBlocks.
Definition secblock.h:1111
SecBlock(const T *ptr, size_type len)
Construct a SecBlock from an array of elements.
Definition secblock.h:789
void Append(size_type count, T value)
Append contents from a value.
Definition secblock.h:1004
bool operator==(const SecBlock< T, A > &t) const
Bitwise compare two SecBlocks.
Definition secblock.h:1095
void Grow(size_type newSize)
Change size and preserve contents.
Definition secblock.h:1160
void New(size_type newSize)
Change size without preserving contents.
Definition secblock.h:1126
size_type SizeInBytes() const
Provides the number of bytes in the SecBlock.
Definition secblock.h:885
void Append(const SecBlock< T, A > &t)
Append contents from another SecBlock.
Definition secblock.h:973
void SetMark(size_t count)
Sets the number of elements to zeroize.
Definition secblock.h:1037
void Assign(const T *ptr, size_type len)
Set contents and size from an array.
Definition secblock.h:898
byte * BytePtr()
Provides a byte pointer to the first element in the memory block.
Definition secblock.h:876
const_iterator end() const
Provides a constant iterator pointing beyond the last element in the memory block.
Definition secblock.h:851
A::const_pointer data() const
Provides a pointer to the first element in the memory block.
Definition secblock.h:861
SecBlock< T, A > & operator+=(const SecBlock< T, A > &t)
Append contents from another SecBlock.
Definition secblock.h:1059
bool empty() const
Determines if the SecBlock is empty.
Definition secblock.h:871
const byte * BytePtr() const
Return a byte pointer to the first element in the memory block.
Definition secblock.h:880
SecBlock< T, A > & operator=(const SecBlock< T, A > &t)
Assign contents from another SecBlock.
Definition secblock.h:1047
size_type size() const
Provides the count of elements in the SecBlock.
Definition secblock.h:867
void resize(size_type newSize)
Change size and preserve contents.
Definition secblock.h:1198
Stack-based SecBlock that grows into the heap.
Definition secblock.h:1268
SecBlockWithHint(size_t size)
construct a SecBlockWithHint with a count of elements
Definition secblock.h:1271
Library configuration file.
Utility functions for the Crypto++ library.
void * memset_z(void *ptr, int val, size_t num)
Memory block initializer.
Definition misc.h:638
const T & STDMAX(const T &a, const T &b)
Replacement function for std::max.
Definition misc.h:666
void SecureWipeArray(T *buf, size_t n)
Sets each element of an array to 0.
Definition misc.h:1491
void memcpy_s(void *dest, size_t sizeInBytes, const void *src, size_t count)
Bounds checking replacement for memcpy()
Definition misc.h:525
const T & STDMIN(const T &a, const T &b)
Replacement function for std::min.
Definition misc.h:655
bool IsAlignedOn(const void *ptr, unsigned int alignment)
Determines whether ptr is aligned to a minimum value.
Definition misc.h:1227
void memmove_s(void *dest, size_t sizeInBytes, const void *src, size_t count)
Bounds checking replacement for memmove()
Definition misc.h:571
A::pointer StandardReallocate(A &alloc, T *oldPtr, typename A::size_type oldSize, typename A::size_type newSize, bool preserve)
Reallocation function.
Definition secblock.h:149
NAMESPACE_END void swap(CryptoPP::SecBlock< T, A > &a, CryptoPP::SecBlock< T, A > &b)
Swap two SecBlocks.
Definition secblock.h:1289
Common C++ header files.
Template class member Rebind.
Definition secblock.h:272