Сообщения Schannel больше, чем cbmaximummessage
Привет,
У меня есть проблема с отправкой сообщения SChannel TLS, превышающего согласованную максимальную длину. Я определил класс, обрабатывающий контекст SChannel (класс my_context), и класс, обрабатывающий сокет, который использует класс my_context для шифрования передаваемых данных.
Когда my_socket.write () вызывается с буфером, большим, чем SecPkgContext_StreamSizes.cbMaximumMessage, часть, большая, чем SecPkgContext_StreamSizes.cbMaximumMessage, не понимается сервером (ни Wireshark).
class my_socket { public: void write(::boost::asio::const_buffers_1 const& buf) { //this signature implies const_buffers_1 i.e. only one buffer at a time auto b = *buf.begin(); auto util = IoBuffer.size() - phContext->GetBufferReservedSize(); char const* begin = ::boost::asio::buffer_cast<char const*>(b); char const* curr = begin; char const* end = begin + ::boost::asio::buffer_size(b); while (curr != end) { auto const buffSz = std::min(util, (size_t)(end - curr)); auto const encryptedMessage = phContext->EncryptMessage( ::boost::asio::buffer(curr, buffSz), IoBuffer); auto const data = ::boost::asio::buffer_cast<char const*>(encryptedMessage); auto const sz = ::boost::asio::buffer_size(encryptedMessage); auto cbData = send(Socket, data, sz, 0); if (cbData != sz) throw std::invalid_argument("Can't send data to the server (error code:" + std::to_string(WSAGetLastError()) + ")"); curr += buffSz; } } private: void _AllocateIoBuffer() { phContext->ResizeBuffer(IoBuffer); } SOCKET Socket; my_context *phContext; std::vector<char> IoBuffer; }; class my_context { [...] public: long RoundUp(long n, long s) { return ((n + s - 1) / s)*s; } int GetBufferReservedSize() { auto const& sz = GetSizes_(); return RoundUp(sz.cbHeader, sz.cbBlockSize) + RoundUp(sz.cbTrailer, sz.cbBlockSize) ; } void ResizeBuffer(std::vector<char>& buf) { auto const& sz = GetSizes_(); buf.reserve(sz.cbHeader + sz.cbMaximumMessage + sz.cbTrailer); buf.resize(sz.cbMaximumMessage); } boost::asio::const_buffer EncryptMessage( boost::asio::const_buffer const& message, std::vector<char>& IoBuffer) const { SecBufferDesc Message; SecBuffer Buffers[4]; auto sz = boost::asio::buffer_size(message); char const* data = boost::asio::buffer_cast<char const*>(message); // Encrypt the request. auto const headerSize = GetSizes_().cbHeader; Buffers[0].pvBuffer = IoBuffer.data(); Buffers[0].cbBuffer = headerSize; Buffers[0].BufferType = SECBUFFER_STREAM_HEADER; CopyMemory(IoBuffer.data() + headerSize, data, sz); Buffers[1].pvBuffer = IoBuffer.data() + headerSize; Buffers[1].cbBuffer = sz; Buffers[1].BufferType = SECBUFFER_DATA; Buffers[2].pvBuffer = IoBuffer.data() + headerSize + sz; Buffers[2].cbBuffer = GetSizes_().cbTrailer; Buffers[2].BufferType = SECBUFFER_STREAM_TRAILER; Buffers[3].BufferType = SECBUFFER_EMPTY; Message.ulVersion = SECBUFFER_VERSION; Message.cBuffers = 4; Message.pBuffers = Buffers; SECURITY_STATUS const scRet = ::EncryptMessage( const_cast<PCtxtHandle>(&hContext), 0, &Message, 0); if (FAILED(scRet)) { throw std::invalid_argument("Unable to ecrypt message (error code:" + std::to_string(scRet) + ")"); } return boost::asio::buffer(IoBuffer, Buffers[0].cbBuffer + Buffers[1].cbBuffer + Buffers[2].cbBuffer); } SecPkgContext_StreamSizes GetSizes_() const { if (Sizes_.cbHeader == Sizes_.cbMaximumMessage == Sizes_.cbTrailer == 0) { SECURITY_STATUS const scRet = ::QueryContextAttributes( const_cast<CtxtHandle*>(&hContext), SECPKG_ATTR_STREAM_SIZES, &Sizes_); if (scRet != SEC_E_OK) { throw std::invalid_argument("Can't get the buffer sizes (error code:" + std::to_string(scRet) + ")"); } } return Sizes_; } CredHandle hClientCreds; CtxtHandle hContext; mutable SecPkgContext_StreamSizes Sizes_; const DWORD dwProtocol = SP_PROT_TLS1_2; };
Что я уже пробовал:
Я попытался зашифровать сообщение одним звонком, но это не удалось.