David Schwartz wrote:
Darryl Miles wrote:

I do not believe the SSL_write() call is allowed to access the
underlying BIO/kernel-socket to read in more data.  I think SSL_write()
is allowed to process any data already read into buffer (from kernel to
OpenSSL library internal buffer) in an attempt to unstall the situation
itself.  But it can't invoke read() on the kernel for it.

If SSL_write has to read from the socket to make forward progress, there is
absolutely no reason it shouldn't just do so. There is no reason it should
compel the application to do it.

My documentation says:

       [T]he return value of SSL_write() will yield SSL_ERROR_WANT_READ or
       SSL_ERROR_WANT_WRITE. As at any time a re-negotiation is possible, a
       call to SSL_write() can also cause read operations! The calling
process
       then must repeat the call after taking appropriate action to satisfy
       the needs of SSL_write(). The action depends on the underlying BIO.
       When using a non-blocking socket, nothing is to be done, but select()
       can be used to check for the required condition. When using a
buffering
       BIO, like a BIO pair, data must be written into or retrieved out of
the
       BIO before being able to continue.

This suggests the exact opposite of what you said. One of these sources is
right and the other is wrong, and it makes a huge difference which!

My understanding, for many years, coincides with this documentation.
However, I can't think of any specific case where this difference would have
affected me, as my coding is extremely defensive and would tolerate either
mechanism without a problem.

"One of these sources is right and the other is wrong" ... Yes, no, maybe... You maybe correct in the detail here, I am going on my hazy-memory of experimenting with this situation and the observable behavior. But I never wrote up notes on the matter not saw fit to improve the documentation.

My conclusions on it were that an SSL_write() can cause a packet decode to complete but only: * If the data for the entire packet has already been read() into the SSL user-space buffer (i.e. no longer in the BIO/kernel). The read-ahead optimization makes it possible for this to happen. * If there is no application data waiting to be destructively removed ahead of the re-negotiation packet. i.e. SSL_read(). Until all application data has been sunk/removed from OpenSSL it won't decode the next packet.

My memory on this was that SSL_write() itself won't call on the BIO to perform a read() but it will attempt to decode the next incoming packet from the data it may already have, this is in the hope that it turns out to be the re-negotiation response (in many situations it gets lucky!). If it decodes the next packet and it turns out to be incoming application data then SSL_write() is stuffed! No amount of calling it again will clear the -1/WANT_READ condition.



The largest part of my previous post was explaining how to handle the situation generalls and calling SSL_read() and then re-trying SSL_write() to see if the condition has cleared it the way to deal with it. You can not rely on repeatedly calling SSL_write() alone to clear the problem. Which was my interpretation of what Jason was asking.



To re-express the same thing another way:

SSL_write() calls can not by-pass the already in-progress inbound application data (to get at the re-negotiation response packet immediately). There is a possibility there is still some application data waiting to be SSL_read() before the re-negotiation SSL protocol packet can be seen, decoded and processed.

Imagine the re-negotiation SSL protocol packet is actually still inside the kernel buffering (waiting for user-space to read() to pull it). Now image that there are at least 2 large full-size application data packets also spanned across the user-space and kernel buffers (ahead of the SSL re-negotiation packet).

SSL_write() has no where to put the data once it has decoded a large full-sized application data packet. Inside OpenSSL there is a rigid buffering scheme, there is a decode buffer into which the encrypted packet is read in from BIO/kernel. There is also a clear-text buffer into which the resultant application data from a single packet decode can be stored. The decode/decyption process only takes place if the clear-text buffer is empty (i.e. user-space has SSL_read() all the previous data from it, so it will attempt to pull in more data and re-fill it).

It is for sure that OpenSSL doesn't have an infinite expandable memory buffer to keep holding application data to allow SSL_write() to find the re-negotiation packet. So it is the worst-case scenario I have in mind when explaining how to handle the matter in my previous post.



The documentation could certainly be improved no matter what the correct way to express the situation is. The docs were written to support the implementation (not the other way around).


Darryl
______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
User Support Mailing List                    openssl-users@openssl.org
Automated List Manager                           majord...@openssl.org

Reply via email to