Для целей 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 есть оптимизирующие компиляторы, которые обнуляют только первый байт — Даниэль Треббиен, 9 ноября ’12 в 12:50
Фоновое чтение:
Убедитесь, что вы полностью понимаете, что Boost Asio буферы не иметь семантики владения. Они только когда-либо ссылка данные, принадлежащие другому объекту.
Что более важно, чем поставленный вопрос, вы можете проверить, достаточно ли долго хранятся данные буфера. Распространенной ловушкой является передача локального в качестве буфера:
std::string response = "OK\r\n\r\n"; asio::async_write(sock_, asio::buffer(response), ...); // OOOPS!!!
Это ведет к Неопределенное поведение немедленно.
IOW const_buffer
это концепция. Существует множество способов построить его поверх (ваших) объектов:
Буферный объект представляет непрерывную область памяти в виде 2-х кортежей, состоящих из указателя и размера в байтах. Кортеж формы
{void*, size_t}
определяет изменяемую (модифицируемую) область памяти. Аналогично, кортеж в форме{const void*, size_t}
определяет постоянную (неизменяемую) область памяти. Эти две формы соответствуют классамmutable_buffer
а такжеconst_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()),
/*...*/
);