randombit / botan

Cryptography Toolkit
https://botan.randombit.net
BSD 2-Clause "Simplified" License
2.57k stars 563 forks source link

TLS boost::asio::ssl compatible library does not work #2635

Closed fxdupont closed 3 years ago

fxdupont commented 3 years ago

I tried to make a small server tool using the TLS "boost::asio::ssl compatible" library but it fails in handshake with an Unknown error from a "basic_flat_buffer too long" exception.

This looks like a mismatch between Botan and boost::beast so I give here the exact environment:

I attached the botan and boost formulas (in the case a config flag matters) and the tool which is derived from the boost c++11 sample for the boost::asio::ssl library. I tried the client derived from the same sample directory and also the tls_client from Botan cli: both made the handshake to fail on the server side. I used wireshark to see the packets: there is nothing particular: the client sends a standard (and between 280-290 bytes) TLS ClientHello and the server closes the connection.

I can help if you need more details or to run test codes. The idea of the boost::asio::ssl compatible library was great and I really want to make it to work in the software I work on which offers the choice between Botan and OpenSSL crypto backends. Even I currently is not about security software I worked many times on security related codes: in fact this is something which comes back often: I think I never stay 10 years without it...

Another (very minor) point: the classes derived from boost::system::error_code should have a virtual destructor to not get problems with the clang/gcc -Wnon-virtual-dtor flag. BTW it is clear these classes will be never used through a pointer to the base class but the compiler does not know... Alternately you can disable locally the warning but IMHO this is a dubious practice.

boostbotan.rb.txt boost.rb.txt

botan_boost_sample_server.cpp.txt

randombit commented 3 years ago

@hrantzsch @reneme any ideas?

hrantzsch commented 3 years ago

Strange! I'm not sure if the homebrew packages are really the issue here. To be certain, can you try compiling this example of an HTTP server with those same versions of Botan and Boost? https://github.com/hrantzsch/botan-tls-stream-server-example

fxdupont commented 3 years ago

I tried the HTTP server example: it went through the handshake but the asynchronous read stalls. According to wireshark I have a Server Hello and co but the Application Data from the client does nothing on the server side until the read timeout is triggered... So it did not help.

I'll try a more direct approach: I'll put some prints and an assert on the boost code which failed with my example. But even if I find a workaround this won't change in the short term the fact that Botan is packaged without the boost part so it could be never used in production with our product (Kea a DHCP server done by ISC).

hrantzsch commented 3 years ago

Thanks for helping us investigate the issue. The read timeout sounds like a different kind of issue to me. We'll try to reproduce the issue on macOS.

Regarding the homebrew package, you could consider using the conan package instead. Botan with Boost is available there.

reneme commented 3 years ago

@hrantzsch and I found the issue in Botan: It seems that TLS::Stream<> does not cope well with being std::move()-ed around for some reason. We'll need to look into the details later.

Anyway, to make your example work, you just need to create said object in-place in your session instead of relying on std::move()-ing the TLS::Stream<>.

A diff says more than a 1000 words:

87,88c87,88
<   session(Botan::TLS::Stream<tcp::socket> socket)
<     : socket_(std::move(socket))
---
>   session(tcp::socket socket, Botan::TLS::Context& ctx)
>     : socket_(std::move(socket), ctx)
170,171c170,171
<                   Botan::TLS::Stream<tcp::socket>(
<                   std::move(socket), context_))->start();
---
>               std::move(socket),
>               context_)->start();
fxdupont commented 3 years ago

I have a mixed feeling about programming language packager but as Kea is a pure C++ software I'll pass a message to my colleagues in charge of packaging.

I was sleeping so I lost your comment. I agree the move can be a source of problems and of course this makes to sample tool to got further.

If you need the ticket to find why the TLS::Stream breaks with its move constructor I leave this ticket open. Otherwise I close it as with your proposed change the handshake no longer triggers the error.

randombit commented 3 years ago

We should ideally work out why TLS::Stream is not move compatible and fix it. Or at the very least delete the relevant conversions - having something compile and then just silently not work is bad news.

reneme commented 3 years ago

We'll have a look into the move-issue with TLS::Stream in the coming days and will close the issue afterwards.

fxdupont commented 3 years ago

I have an unit test reusing the TCP connection. For OpenSSL it means to call SSL_clear, I thought about using the move assignment to get a fresh TLS stream but even it could work when the move will be fixed currently I believe the server side should not be very happy with this, i.e. this is clearly outside use cases specified in RFCs... So I'll give up in this point: the unit test is from pure TCP and should not be extended to TLS.

So please close the issue at your hand.

hrantzsch commented 3 years ago

We validated that your example runs smoothly with the patch linked above :+1: