SSL_read will not return anything until it has received and verified a
full record.  It will do its own buffering, and all you have to do is
respond to it.  (If you're in a proxy/relay environment, it's possible
that the kernel will not have received the next packet to go into the
buffer, so you'll be spinning your wheels by looping for it.)  It
won't report anything until it has verified that the record is
correct.

So, you might as well continue as far as you're able (SSL_read will
check its pending buffer-to-application, then perform the read on the
socket, process it as much as possible, and then return what it can to
the application).  Then, skip the loop that you're trying to do and
continue.  The underlying SSL library will handle all the necessary
buffering for itself, and the kernel itself will also provide a
certain amount of buffering per TCP connection to allow you to handle
other TCP streams.  select() will tell you when there's something that
can be read on the TCP connection -- but all it can say is "there's
additional encrypted data here".  It can't tell you whether it
constitutes a complete SSL record.

The reason why SSL_pending returns 0 before an SSL_read is because
SSL_read is the only thing that actually decrypts the data.
SSL_pending checks the number of application data bytes that SSL_read
has sitting in its queue for input; it does not call SSL_read to
actually process any record that is pending processing.

-Kyle H

On Tue, Mar 31, 2009 at 5:29 AM, Francis GASCHET <f...@numlog.fr> wrote:
> Hello Kyle,
>
>
> Thank you for these explanations. Things are becoming clearer.
> An important point about the application is : it's a relay (gateway). So it
> doesn't have only to take care of the SSL side, but also of the relayed
> application (private) side.
> It's a non-blocking environment, so I am quite apprehensive about loops.
> I need to be awaken also when something arrive from the private side (pure
> TCP socket ). So I need select and I've to combine TCP sockets and SSL
> "socket" in the same monitoring loop.
>>
>> You can suppress this behavior (and ensure that you could loop like
>> that) by calling SSL[_CTX]_set_mode(ctx, SSL_MODE_AUTO_RETRY).
>>
>
> From the man page : "The flag SSL_MODE_AUTO_RETRY will cause read/write
> operations to only return after the handshake and successful completion.
> So I fear that it's not a that good idea in my environment. Am I wrong ?
>>
>> SSL should be the only thing that handles things like
>> MAX_RECORD_SIZE.
>
> OK, but from the source, I discovered that SSL_read is blocking until it
> receives a complete record. So, if I want to be awaken with select I must
> either:
>
>   * make a read for data length >= "max record length", but I depend
>     on internal value (XXXXXX_LENGTH) which is not very clean,
>   * make a read for data length = read buffer length (some kbytes) and
>     then loop on SSL_pending and SSL_read to get the rest of the
>     record, until SSL_pending returns 0. In that case, after the first
>     SSL_read has returned something select is useless.
>
> Anyway I'm blocked in the first SSL_read while SSL is reading the whole
> record so both method should give the same result in term of response time,
> and the second one is cleaner. Is it correct?
>
> Best regards,
>
> --
> Francis GASCHET / NUMLOG
> http://www.numlog.fr
> Tel.: +33 (0) 130 791 616
> Fax.: +33 (0) 130 819 286
>
> You can suppress this behavior (and ensure that you could loop like
> that) by calling SSL[_CTX]_set_mode(ctx, SSL_MODE_AUTO_RETRY).
>
>
>
>
>
> Le 03/30/2009 11:15 PM Kyle Hamilton a écrit  :
>>
>> SSL will return SSL_ERROR_WANT_READ if it needs to read more.  It will
>> return SSL_ERROR_WANT_WRITE if it needs to write things out on that
>> socket before it can do anything else (for example, during a
>> renegotiation).  (There is no fixed upper bound of times this can
>> happen, so beware of going into an infinite loop until the OS decides
>> that the remote has died and closes the socket.)
>>
>> You can suppress this behavior (and ensure that you could loop like
>> that) by calling SSL[_CTX]_set_mode(ctx, SSL_MODE_AUTO_RETRY).
>>
>> Generally, SSL_read will try to behave like read(), and SSL_write will
>> try to behave like write() -- that is, you can request of the library
>> that it return you a maximum number of bytes, and it'll buffer the
>> rest.  SSL should be the only thing that handles things like
>> MAX_RECORD_SIZE.
>>
>> Instead of select(), you can use a loop through your available SSL
>> objects with SSL_pending() to see if there is any application data in
>> the queue that can be read.  select() should be used only on the
>> OS-level sockets, to figure out if the SSL layer needs to be called to
>> handle that data.
>>
>> (This is a problem of a "leaky abstraction" -- you need to be aware of
>> the difference between the "application layer" (i.e., your app, that
>> uses the services of the library) and the "OS layer" (which is only
>> manipulated by the library, though you have to read and respond to its
>> state by calling the library)... and realize that if you also handle
>> unencrypted connections, the "application layer" and the "OS layer"
>> are the same on those connections.)
>>
>> -Kyle H
>>
>> On Mon, Mar 30, 2009 at 11:03 AM, Francis GASCHET <f...@numlog.fr> wrote:
>>
>>>
>>> Hello David,
>>>
>>> Thank you for this explanation.
>>> I've a good book from Eric Rescorla, but may be I jumped too quickly to
>>> the
>>> API and didn't learn enough the concepts!
>>>
>>> So If I correctly understand, I must try to read a MAX_RECORD_SIZE buffer
>>> (16383 bytes) when select says "There is something ready to be read", and
>>> I'll receive the error "SSL_WANT READ" until the complete record will be
>>> processed by SSL. And only then, the SSL_read will return the record and
>>> its
>>> real length.
>>> It looks like if SSL says to the system "I've something ready" when it
>>> begins to receive a new record. So if I read only the beginning of the
>>> record because I use a too small buffer, I'll never be notified for the
>>> remaining bytes.
>>>
>>> Am I right or did I missed something.
>>>
>>> Thanks anyway.
>>> Best regards,
>>>
>>> --
>>> Francis GASCHET / NUMLOG
>>> http://www.numlog.fr
>>> Tel.: +33 (0) 130 791 616
>>> Fax.: +33 (0) 130 819 286
>>>
>>>
>>>
>>>
>>> Le 03/27/2009 06:29 AM David Schwartz a écrit  :
>>>
>>>>>
>>>>> the application read the first
>>>>> 1500 bytes, then "select(...)" no more indicates that something has to
>>>>> be read on the fd. So the OFTP application behind the gateway doesn't
>>>>> send the new "credit authorisation" because it didn't receive the
>>>>> complete previous credit. And the sender waits until its inactivity
>>>>> timer (more or less 2 minutes) triggers.
>>>>>
>>>>>
>>>>
>>>> You cannot call 'select' to wait for data to be received if that data
>>>> has
>>>> already been received. You should not ever assume that OpenSSL is
>>>> waiting
>>>> for data to arrive on the socket unless it tells you this.
>>>>
>>>> You have broken the fundamental rule of OpenSSL. You *assumed* that
>>>> encrypted data received over the wire would mean decrypted data received
>>>> from OpenSSL. So because you wanted decrypted data from OpenSSL, you
>>>> waited
>>>> for encrypted data on the wire.
>>>>
>>>> Now this is *sometimes* true. But in this case, it was not true. So your
>>>> assumption was false.
>>>>
>>>> Do not ever, ever, ever assume that you know what OpenSSL needs to make
>>>> further progress. Because if you assume wrong, you are screwed. There is
>>>> no
>>>> reason you should ever need to make this assumption, since OpenSSL will
>>>> tell
>>>> you what it needs.
>>>>
>>>> DS
>>>>
>>>>
>>>> ______________________________________________________________________
>>>> OpenSSL Project                                 http://www.openssl.org
>>>> User Support Mailing List                    openssl-us...@openssl.org
>>>> Automated List Manager                           majord...@openssl.org
>>>>
>>>>
>>>>
>>>>
>>>
>>> ______________________________________________________________________
>>> OpenSSL Project                                 http://www.openssl.org
>>> User Support Mailing List                    openssl-us...@openssl.org
>>> Automated List Manager                           majord...@openssl.org
>>>
>>>
>>
>> ______________________________________________________________________
>> OpenSSL Project                                 http://www.openssl.org
>> User Support Mailing List                    openssl-us...@openssl.org
>> Automated List Manager                           majord...@openssl.org
>>
>>
>>
>
> ______________________________________________________________________
> OpenSSL Project                                 http://www.openssl.org
> User Support Mailing List                    openssl-us...@openssl.org
> Automated List Manager                           majord...@openssl.org
>
______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
User Support Mailing List                    openssl-users@openssl.org
Automated List Manager                           majord...@openssl.org

Reply via email to