Secure deallocation of boost::asio::const_buffer

blech

For the purpose of PA:DSS I need to be sure that boost::asio::const_buffer (e.g. in boost::asio::async_write) will be zeroed when coming out of scope.

With a STL containers I can substitute a allocator/deallocator like this:

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

However I have no idea how to achieve the same with boost::asio::const_buffer, at least not in a way which would still let boost::asio::async_write to consume it. Also I don't want to reinvent the wheel (if there is any).

sehe

Short answer: Asio buffers don't own their memory, so they should not be responsible for disposing of it either.

First off, you should not use

std::memset(p, 0, n * sizeof(T));

Use a function like SecureZeroMemory instead: How-to ensure that compiler optimizations don't introduce a security risk?

I realize you had volatile there for this reason, but it might not always be honoured like you expect:

Your secure_memset function might not be sufficient. According to http://open-std.org/jtc1/sc22/wg14/www/docs/n1381.pdf there are optimizing compilers that will only zero the first byte – Daniel Trebbien Nov 9 '12 at 12:50

Background reading:


On to ASIO

Make sure you fully realize that Boost Asio buffers have no ownership semantics. They only ever reference data owned by another object.

More importantly than the question posed, you might want to check that you keep around the buffer data long enough. A common pitfall is to pass a local as a buffer:

std::string response = "OK\r\n\r\n";
asio::async_write(sock_, asio::buffer(response), ...); // OOOPS!!!

This leads to Undefined Behaviour immediately.

IOW const_buffer is a concept. There are a gazillion ways to construct it on top of (your own) objects:

documentation

A buffer object represents a contiguous region of memory as a 2-tuple consisting of a pointer and size in bytes. A tuple of the form {void*, size_t} specifies a mutable (modifiable) region of memory. Similarly, a tuple of the form {const void*, size_t} specifies a const (non-modifiable) region of memory. These two forms correspond to the classes mutable_buffer and const_buffer, respectively

So, let's assume you have your buffer type

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;
};

Then you can simply pass it where you want to use it:

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

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related