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 : #include <vector> 15 : 16 : // 17 : // Allocator that locks its contents from being paged 18 : // out of memory and clears its contents before deletion. 19 : // 20 : template <typename T> 21 : struct secure_allocator { 22 : using value_type = T; 23 : 24 : secure_allocator() = default; 25 : template <typename U> 26 : secure_allocator(const secure_allocator<U>&) noexcept {} 27 : 28 3887754 : T* allocate(std::size_t n) 29 : { 30 3887754 : T* allocation = static_cast<T*>(LockedPoolManager::Instance().alloc(sizeof(T) * n)); 31 3887754 : if (!allocation) { 32 0 : throw std::bad_alloc(); 33 : } 34 3887754 : return allocation; 35 : } 36 : 37 3884310 : void deallocate(T* p, std::size_t n) 38 : { 39 3884310 : if (p != nullptr) { 40 3884310 : memory_cleanse(p, sizeof(T) * n); 41 3884310 : } 42 3884310 : LockedPoolManager::Instance().free(p); 43 3884310 : } 44 : 45 : template <typename U> 46 : friend bool operator==(const secure_allocator&, const secure_allocator<U>&) noexcept 47 : { 48 : return true; 49 : } 50 : template <typename U> 51 10714 : friend bool operator!=(const secure_allocator&, const secure_allocator<U>&) noexcept 52 : { 53 10714 : return false; 54 : } 55 : }; 56 : 57 : // This is exactly like std::string, but with a custom allocator. 58 : // TODO: Consider finding a way to make incoming RPC request.params[i] mlock()ed as well 59 : typedef std::basic_string<char, std::char_traits<char>, secure_allocator<char> > SecureString; 60 : 61 : typedef std::vector<unsigned char, secure_allocator<unsigned char> > SecureVector; 62 : template<typename T> 63 : struct SecureUniqueDeleter { 64 2963691 : void operator()(T* t) noexcept { 65 2963691 : secure_allocator<T>().deallocate(t, 1); 66 2963691 : } 67 : }; 68 : 69 : template<typename T> 70 : using secure_unique_ptr = std::unique_ptr<T, SecureUniqueDeleter<T>>; 71 : 72 : template<typename T, typename... Args> 73 2963691 : secure_unique_ptr<T> make_secure_unique(Args&&... as) 74 : { 75 2963691 : T* p = secure_allocator<T>().allocate(1); 76 : 77 : // initialize in place, and return as secure_unique_ptr 78 : try { 79 2963691 : return secure_unique_ptr<T>(new (p) T(std::forward(as)...)); 80 : } catch (...) { 81 : secure_allocator<T>().deallocate(p, 1); 82 : throw; 83 : } 84 : } 85 : 86 : #endif // BITCOIN_SUPPORT_ALLOCATORS_SECURE_H