2019-09-02 10:28:14 +00:00
|
|
|
#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 <windows.h>
|
|
|
|
|
|
|
|
#include <string>
|
|
|
|
|
|
|
|
// based on https://codereview.stackexchange.com/questions/107991/hacking-a-securestring-based-on-stdbasic-string-for-c
|
|
|
|
|
2020-03-05 15:30:50 +00:00
|
|
|
namespace FSecure
|
2019-09-02 10:28:14 +00:00
|
|
|
{
|
|
|
|
/// Minimal allocator zeroing on deallocation
|
|
|
|
/// @tparam T type to allocate
|
|
|
|
template <typename T>
|
|
|
|
struct SecureAllocator
|
|
|
|
{
|
|
|
|
using value_type = T;
|
|
|
|
using propagate_on_container_move_assignment = typename std::allocator_traits<std::allocator<T>>::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 <class U>
|
|
|
|
constexpr SecureAllocator(const SecureAllocator<U>&) 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<T>{}.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<T>{}.deallocate(p, n);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
/// Equality operator
|
|
|
|
/// @returns true
|
|
|
|
template <typename T, typename U>
|
|
|
|
constexpr bool operator== (const SecureAllocator<T>&, const SecureAllocator<U>&) noexcept
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Inequality operator
|
|
|
|
/// @returns false
|
|
|
|
template <typename T, typename U>
|
|
|
|
constexpr bool operator!= (const SecureAllocator<T>&, const SecureAllocator<U>&) noexcept
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2020-03-04 16:46:01 +00:00
|
|
|
template<typename CharT>
|
|
|
|
using BasicSecureString = std::basic_string<CharT, std::char_traits<CharT>, SecureAllocator<CharT>>;
|
|
|
|
|
2019-09-02 10:28:14 +00:00
|
|
|
/// alias for string with SecureAllocator
|
2020-03-04 16:46:01 +00:00
|
|
|
using SecureString = BasicSecureString<char>;
|
2019-09-02 10:28:14 +00:00
|
|
|
|
|
|
|
/// alias for wstring with SecureAllocator
|
2020-03-04 16:46:01 +00:00
|
|
|
using SecureWString = BasicSecureString<wchar_t>;
|
2019-09-02 10:28:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
namespace std
|
|
|
|
{
|
|
|
|
/// Specialized SecureString destructor.
|
|
|
|
/// Overwrites internal buffer (if SSO is in effect)
|
|
|
|
template<>
|
2020-03-06 14:23:57 +00:00
|
|
|
inline basic_string<char, std::char_traits<char>, FSecure::SecureAllocator<char>>::~basic_string() noexcept
|
2019-09-02 10:28:14 +00:00
|
|
|
{
|
|
|
|
// Clear internal buffer if SSO is in effect
|
2020-01-02 16:46:58 +00:00
|
|
|
#if _MSC_VER >= 1920 // v142 toolset
|
|
|
|
auto& _My_data = _Mypair._Myval2;
|
|
|
|
#elif _MSC_VER >= 1910 // v141 toolset
|
2019-09-02 10:28:14 +00:00
|
|
|
auto& _My_data = this->_Get_data();
|
2020-01-02 16:46:58 +00:00
|
|
|
#elif
|
|
|
|
#error Unsupported toolset
|
|
|
|
#endif
|
2019-09-02 10:28:14 +00:00
|
|
|
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<>
|
2020-03-06 14:23:57 +00:00
|
|
|
inline basic_string<wchar_t, std::char_traits<wchar_t>, FSecure::SecureAllocator<wchar_t>>::~basic_string() noexcept
|
2019-09-02 10:28:14 +00:00
|
|
|
{
|
|
|
|
// Clear internal buffer if SSO is in effect
|
2020-01-02 16:46:58 +00:00
|
|
|
#if _MSC_VER >= 1920 // v142 toolset
|
|
|
|
auto& _My_data = _Mypair._Myval2;
|
|
|
|
#elif _MSC_VER >= 1910 // v141 toolset
|
2019-09-02 10:28:14 +00:00
|
|
|
auto& _My_data = this->_Get_data();
|
2020-01-02 16:46:58 +00:00
|
|
|
#elif
|
|
|
|
#error Unsupported toolset
|
|
|
|
#endif
|
2019-09-02 10:28:14 +00:00
|
|
|
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();
|
|
|
|
}
|
|
|
|
}
|