boost::asio::const_buffer的安全回收

Secure deallocation of boost::asio::const_buffer

本文关键字:安全 asio const boost buffer      更新时间:2023-10-16

对于PA:DSS的目的,我需要确保boost::asio::const_buffer(例如在boost::asio::async_write)将在超出作用域时归零。

对于STL容器,我可以像这样替换分配器/释放器:

    void deallocate(volatile pointer p, size_type n) {
        std::memset(p, 0, n * sizeof(T));
        ::operator delete(p);
    }

然而,我不知道如何用boost::asio::const_buffer实现相同的目标,至少不是以一种仍然让boost::asio::async_write消耗它的方式。我也不想重新发明轮子(如果有的话)。

简短的回答:Asio缓冲区不拥有自己的内存,所以它们也不应该负责处理内存

首先,你应该而不是使用
std::memset(p, 0, n * sizeof(T));

使用像SecureZeroMemory这样的函数:如何确保编译器优化不会引入安全风险?

我知道你有volatile是出于这个原因,但它可能并不总是像你期望的那样荣幸:

您的secure_memset函数可能不够。根据http://open-std.org/jtc1/sc22/wg14/www/docs/n1381.pdf,有优化编译器只会将第一个字节归零- Daniel Trebbien Nov 9 '12 at 12:50

背景阅读:

  • https://cryptocoding.net/index.php/Coding_rules Clean_memory_of_secret_data
  • http://blog.quarkslab.com/a-glance-at-compiler-internals-keep-my-memset.html

On to ASIO

确保你完全意识到Boost Asio缓冲区没有所有权语义。它们只引用另一个对象拥有的数据。

比所提出的问题更重要的是,您可能希望检查缓冲区数据是否保留了足够长的时间。一个常见的缺陷是将一个局部变量作为缓冲区传递:

std::string response = "OKrnrn";
asio::async_write(sock_, asio::buffer(response), ...); // OOOPS!!!

这将立即导致未定义行为。

low const_buffer是一个概念。有无数种方法可以在(你自己的)对象上构造它:

文档

缓冲区对象表示一个连续的内存区域,它是一个由指针和大小(以字节为单位)组成的二元组。{void*, size_t}形式的元组指定了一个可变(可修改)的内存区域。类似地,形式为{const void*, size_t}的元组指定了一个const(不可修改的)内存区域。这两种形式分别对应于mutable_bufferconst_buffer

那么,假设你的缓冲区类型是

struct SecureBuffer
{
     ~SecureBuffer() { shred(); }
     size_t      size() const { return length_; }
     char const* data() const { return data_; }
     // ...
   private:
     void shred(); // uses SecureZeroMemory etc.
     std::array<char, 1024> data_ = {0};
     size_t length_ = 0u;
};

然后你可以简单地传递到你想要使用它的地方:

SecureBuffer secret; // member variable (lifetime exceeds async operation)
// ... set data
boost::asio::async_write(sock_,
     boost::asio::buffer(secret.data(), secret.size()),
     /*...*/
    );