secblock.h 51 KB

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