LCOV - code coverage report
Current view: top level - src/support/allocators - secure.h (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 18 19 94.7 %
Date: 2026-06-25 07:23:43 Functions: 12 12 100.0 %

          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

Generated by: LCOV version 1.16