#pragma once // For SecureZeroMemory #ifndef NOMINMAX # define NOMINMAX //< Exclude min and max macros from windows.h. #endif #define WIN32_LEAN_AND_MEAN //< Exclude rarely-used stuff from Windows headers. #include #include // based on https://codereview.stackexchange.com/questions/107991/hacking-a-securestring-based-on-stdbasic-string-for-c namespace FSecure { /// Minimal allocator zeroing on deallocation /// @tparam T type to allocate template struct SecureAllocator { using value_type = T; using propagate_on_container_move_assignment = typename std::allocator_traits>::propagate_on_container_move_assignment; /// Default constructor constexpr SecureAllocator() = default; /// Defaulted copy constructor /// @param other SecureAllocator constexpr SecureAllocator(const SecureAllocator&) = default; /// Other type constructor /// @tparam U - different type /// @param other SecureAllocator template constexpr SecureAllocator(const SecureAllocator&) noexcept { } /// Allocate memory for n T objects /// @param n - count of T objects to allocate /// @returns pointer to allocated memory static T* allocate(std::size_t n) { return std::allocator{}.allocate(n); } /// Clear and deallocate memory for n T objects /// @param p - memory pointer /// @param n - count of T objects to deallocate static void deallocate(T* p, std::size_t n) noexcept { SecureZeroMemory(p, n * sizeof * p); std::allocator{}.deallocate(p, n); } }; /// Equality operator /// @returns true template constexpr bool operator== (const SecureAllocator&, const SecureAllocator&) noexcept { return true; } /// Inequality operator /// @returns false template constexpr bool operator!= (const SecureAllocator&, const SecureAllocator&) noexcept { return false; } template using BasicSecureString = std::basic_string, SecureAllocator>; /// alias for string with SecureAllocator using SecureString = BasicSecureString; /// alias for wstring with SecureAllocator using SecureWString = BasicSecureString; } namespace std { /// Specialized SecureString destructor. /// Overwrites internal buffer (if SSO is in effect) template<> inline basic_string, FSecure::SecureAllocator>::~basic_string() noexcept { // Clear internal buffer if SSO is in effect #if _MSC_VER >= 1920 // v142 toolset auto& _My_data = _Mypair._Myval2; #elif _MSC_VER >= 1910 // v141 toolset auto& _My_data = this->_Get_data(); #elif #error Unsupported toolset #endif if (!_My_data._Large_string_engaged()) SecureZeroMemory(_My_data._Bx._Buf, sizeof _My_data._Bx._Buf); // This is a copy of basic_string dtor _Tidy_deallocate(); } /// Specialized SecureWString destructor. /// Overwrites internal buffer (if SSO is in effect) template<> inline basic_string, FSecure::SecureAllocator>::~basic_string() noexcept { // Clear internal buffer if SSO is in effect #if _MSC_VER >= 1920 // v142 toolset auto& _My_data = _Mypair._Myval2; #elif _MSC_VER >= 1910 // v141 toolset auto& _My_data = this->_Get_data(); #elif #error Unsupported toolset #endif if (!_My_data._Large_string_engaged()) SecureZeroMemory(_My_data._Bx._Buf, sizeof _My_data._Bx._Buf); // This is a copy of basic_string dtor _Tidy_deallocate(); } }