Branch data Line data Source code
1 : : // Copyright (c) 2009-2010 Satoshi Nakamoto 2 : : // Copyright (c) 2009-2021 The Bitcoin Core developers 3 : : // Distributed under the MIT software license, see the accompanying 4 : : // file COPYING or http://www.opensource.org/licenses/mit-license.php. 5 : : 6 : : #ifndef BITCOIN_SUPPORT_ALLOCATORS_SECURE_H 7 : : #define BITCOIN_SUPPORT_ALLOCATORS_SECURE_H 8 : : 9 : : #include <support/lockedpool.h> 10 : : #include <support/cleanse.h> 11 : : 12 : : #include <memory> 13 : : #include <string> 14 : : 15 : : // 16 : : // Allocator that locks its contents from being paged 17 : : // out of memory and clears its contents before deletion. 18 : : // 19 : : template <typename T> 20 : : struct secure_allocator { 21 : : using value_type = T; 22 : : 23 : : secure_allocator() = default; 24 : : template <typename U> 25 : : secure_allocator(const secure_allocator<U>&) noexcept {} 26 : : 27 : 3 : T* allocate(std::size_t n) 28 : : { 29 : 3 : T* allocation = static_cast<T*>(LockedPoolManager::Instance().alloc(sizeof(T) * n)); 30 [ + - ][ # # ]: 3 : if (!allocation) { 31 : 0 : throw std::bad_alloc(); 32 : : } 33 : 3 : return allocation; 34 : : } 35 : : 36 : 3 : void deallocate(T* p, std::size_t n) 37 : : { 38 [ + - ][ + - ]: 3 : if (p != nullptr) { [ # # ] 39 : 3 : memory_cleanse(p, sizeof(T) * n); 40 : 3 : } 41 : 3 : LockedPoolManager::Instance().free(p); 42 : 3 : } 43 : : 44 : : template <typename U> 45 : : friend bool operator==(const secure_allocator&, const secure_allocator<U>&) noexcept 46 : : { 47 : : return true; 48 : : } 49 : : template <typename U> 50 : : friend bool operator!=(const secure_allocator&, const secure_allocator<U>&) noexcept 51 : : { 52 : : return false; 53 : : } 54 : : }; 55 : : 56 : : // This is exactly like std::string, but with a custom allocator. 57 : : // TODO: Consider finding a way to make incoming RPC request.params[i] mlock()ed as well 58 : : typedef std::basic_string<char, std::char_traits<char>, secure_allocator<char> > SecureString; 59 : : 60 : : template<typename T> 61 : : struct SecureUniqueDeleter { 62 : 0 : void operator()(T* t) noexcept { 63 [ # # ]: 0 : secure_allocator<T>().deallocate(t, 1); 64 : 0 : } 65 : : }; 66 : : 67 : : template<typename T> 68 : : using secure_unique_ptr = std::unique_ptr<T, SecureUniqueDeleter<T>>; 69 : : 70 : : template<typename T, typename... Args> 71 : 0 : secure_unique_ptr<T> make_secure_unique(Args&&... as) 72 : : { 73 : 0 : T* p = secure_allocator<T>().allocate(1); 74 : : 75 : : // initialize in place, and return as secure_unique_ptr 76 : : try { 77 : 0 : return secure_unique_ptr<T>(new (p) T(std::forward(as)...)); 78 : : } catch (...) { 79 : : secure_allocator<T>().deallocate(p, 1); 80 : : throw; 81 : : } 82 : : } 83 : : 84 : : #endif // BITCOIN_SUPPORT_ALLOCATORS_SECURE_H