1

boost::asio library provides support for SSL encrypted traffic over sockets by wrapping socket objects in boost::asio::ssl::stream decorator class template. For example:

boost::asio::ssl::stream<boost::asio::ip::tcp::socket> sslSocket;

Some operations of tcp::socket are not supported by ssl::stream. Calling ssl::stream::next_layer method returns reference to wrapped object and this way not supported by ssl::stream operations can be performed directly on wrapped object.

However it seems logical for me that performing read and write operations directly on wrapped socket object bypasses SSL decryption and encryption and for correct SSL behavior read and write on sslSocket must be performed directly over wrapping ssl::stream object.

Is this right or I can freely perform read and write operation on wrapped object?

bobeff
  • 3,543
  • 3
  • 34
  • 62

1 Answers1

3

Not only does using the underlying socket bypass the encryption, it bypasses all of the protocol. Including handshakes, (re)negotiation, side-channels, keepalive etc.

There's no actual guarantee that it would work at all. The only thing you can expect to work is when you use the underlying socket before initializing any SSL operation for the first time.

Beyond that, it's like writing random data to the filedescriptor of a socket that is managed by openssl.

sehe
  • 374,641
  • 47
  • 450
  • 633
  • Is it really the case that the underlying socket is managed by openssl? Openssl performs the handshake on an already connected TCP socket. Anyway, this is all relevant to the question I ask here: https://stackoverflow.com/questions/70742818/is-it-possible-to-use-an-asio-ssl-stream-class-to-alternate-between-encrypted-an – Fabio Jan 18 '22 at 11:14
  • @Fabio depending on what one means with "being managed", yes. I meant the stream, as in the semantics of the data flowing through it. Until you shutdown. I feel it's trivially true you can ssl::stream::shutdown without closing the underlying socket. However, I'm not sure whether [the ASIO implementation or openssl] performs a BSD/Posix [`shutdown`](https://man7.org/linux/man-pages/man2/shutdown.2.html) on the underlying socket. If so, that means you cannot proceed unencrypted on the same channel. If not, that's "trivially" possible (as in, without any other obstacles) – sehe Jan 18 '22 at 11:28
  • Indeed, it seems much more complicate than I thought. Experimenting, just after the handshake, the client side `next_layer` socket still contains 510 bytes. If I read them, then I can use the `next_layer` sockets on both client and server to exchange messages in clear, but when I try a new message from client to server using the ssl stream, the server complains about bad MAC. – Fabio Jan 18 '22 at 11:39
  • 1
    And doing that is just Undefined Behaviour. The way packets buffer depends on many things including hardware. If you inject data into the underlying stream between `handshake()` and `shutdown()` the results are very much unspecified, because the stream is **indeed** managed by OpenSSL internally. Don't ever do that. – sehe Jan 18 '22 at 11:44
  • Noted thanks. However it seems this must be an asio/openssl specific architecture. From a conceptual point of view at some point the stream is passed on to the kernel and to the nic. There should be to do multiplexing (encrypted/non-encrypted) intercepting and controlling the stream flow in a point deep enough that it does not affect the ssl stream state variables. – Fabio Jan 18 '22 at 13:39
  • @Fabio But it doesn't affect the ssl stream state variables! That's why it goes out of sync with reality. Perhaps a more hygienic statement of your point would have been that you wonder whether there is a way to force all state-dependent buffer out on the wire. I think, in short the best answer to that could be SSL shutdown, but you need to check the documentation for your specific use case. – sehe Jan 18 '22 at 18:13
  • what I want to do is to introduce a flag for encrypted (1) or unencrypted (0) messages, then multiplex on the wire, e.g., on the wire I transmit: 0:someplaintext, 1:someEncryptedtext, 1:someOtherEncryptedText,, 0:someotherplaintext, etc... So shutdown is not the solution, as then I have to redo the handshake every time I have a new encrypted message. I think I will drop asio wrapper around openssl, and implement my own ssl stream class using Crypto++. – Fabio Jan 19 '22 at 04:44
  • 1
    @Fabio It sounds like you need something other than a transparent transport layer encryption framework (that's what SSL provides). Otherwise it's square pegs in round holes. I think you might like to look at the http://www.noiseprotocol.org/ framework. And in general the book [Real World Cryptography](https://livebook.manning.com/book/real-world-cryptography/chapter-9) by [David Wong](https://twitter.com/cryptodavidw), which is freely available and I can't recommend enough. – sehe Jan 19 '22 at 10:23