Hi.

I noticed your latest mail thread about ssl renegotiations and this commit
by hlinnaka:
https://github.com/postgres/postgres/commit/272923a0a6956187471df4f032eee06559520390
and how renegotiation is done since that.

Before this commit, after sending a Hello Request, the backend waits until
the handshake was completed (it blocks while waiting for a Client Hello).

After this commit, the backend continues to send application data and in
the next SSL_read, the handshake messages from the client are processed.

However, there is a problem here:
https://github.com/postgres/postgres/blob/1c2b7c0879d83ff79e4adf2c0a883df92b713da4/src/backend/libpq/be-secure-openssl.c#L655

First, SSL_num_renegotiations(port->ssl) always seems to return 1 after
calling SSL_renegotiate, so that check below will never throw an error. So
clients could now simply ignore Hello Requests and no one would complain.

Second, the way of checking the limit that way (if it worked) in
be_tls_write is kind of strange, since if writing much data (more than 1
kb) before doing a SSL_read, the client's handshake message (Client Hello)
is never processed, so then the handshake will never be able to complete
before the renegotiation limit is hit and a fatal error would be thrown. It
would somehow be better to wait if the client sends more than allowed
without responding to the Hello Request. But clients have the same problem,
they might write a lot of data without repeatingly polling the socket if
there are Hello Requests available.

One benefit now is however that the server doesn't have to wait the
roundtrip after sending a Hello Request until it receives the Client Hello,
but instead can send application data interleaved while waiting. However,
OpenSSL is broken (as you've already noticed) since it itself does not
accept interleaved application data with handshake messages (application
data received after Client Hello are considered unexpected messages), so
the benefit can currently not be used by the client. See the recently
posted http://www.mail-archive.com/openssl-dev@openssl.org/msg38217.html.
Also, Microsoft's SslStream doesn't work with renegotiations after this
commit (but here it is SslStream's fault since it doesn't handle
interleaved messages correctly).

SSL_do_renegotiate, which now is removed, was also totally broken since
OpenSSL will send an unexpected message if application data is received
from that point, which could be data in the read buffer that the client has
already sent.

The best thing would be if OpenSSL could fix their issues. This issue is
known:
http://rt.openssl.org/Ticket/Display.html?id=2481&user=guest&pass=guest
since 2011 but they haven't fixed it yet...

I honestly wonder why postgres uses renegotiation at all. The motivation
that cryptoanalysis is easier as more data is sent seems quite far-fetched.
Since often the same session is used after renegotiation, the same master
secret will still be used. Is there anyone that has successfully hacked a
long ssl session by doing cryptoanalysis?

/Emil

Reply via email to