// Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2021 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #ifndef BITCOIN_SUPPORT_ALLOCATORS_SECURE_H #define BITCOIN_SUPPORT_ALLOCATORS_SECURE_H #include #include #include #include // // Allocator that locks its contents from being paged // out of memory and clears its contents before deletion. // template struct secure_allocator { using value_type = T; secure_allocator() = default; template secure_allocator(const secure_allocator&) noexcept {} T* allocate(std::size_t n) { T* allocation = static_cast(LockedPoolManager::Instance().alloc(sizeof(T) * n)); if (!allocation) { throw std::bad_alloc(); } return allocation; } void deallocate(T* p, std::size_t n) { if (p != nullptr) { memory_cleanse(p, sizeof(T) * n); } LockedPoolManager::Instance().free(p); } template friend bool operator==(const secure_allocator&, const secure_allocator&) noexcept { return true; } template friend bool operator!=(const secure_allocator&, const secure_allocator&) noexcept { return false; } }; // This is exactly like std::string, but with a custom allocator. // TODO: Consider finding a way to make incoming RPC request.params[i] mlock()ed as well typedef std::basic_string, secure_allocator > SecureString; template struct SecureUniqueDeleter { void operator()(T* t) noexcept { secure_allocator().deallocate(t, 1); } }; template using secure_unique_ptr = std::unique_ptr>; template secure_unique_ptr make_secure_unique(Args&&... as) { T* p = secure_allocator().allocate(1); // initialize in place, and return as secure_unique_ptr try { return secure_unique_ptr(new (p) T(std::forward(as)...)); } catch (...) { secure_allocator().deallocate(p, 1); throw; } } #endif // BITCOIN_SUPPORT_ALLOCATORS_SECURE_H