How to handle OpenSSL SSL_ERROR_WANT_READ / WANT_WRITE on non-blocking sockets

The OpenSSL library allows you to read from the base socket with SSL_read and write to it using SSL_write. These functions can be returned using SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE depending on the requirements of the ssl protocol (for example, when rebuilding a connection).

I really don't understand what the API wants me to do with these results.

Mapping a server application that accepts client connections, establishes a new ssl session, blocks the underlying socket, and then adds a filedescriptor to the select / poll / epoll loop.

If the client sends data, the main loop sends it to ssl_read. What needs to be done here if SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE is returned? WANT_READ can be easy, because the next main loop iteration can only lead to another ssl_read. But if ssl_read returns WANT_WRITE, with what parameters should it be called? And why does the library not issue the call itself?

If the server wants to send some data to the client, it will use ssl_write. Again, what if WANT_READ or WANT_WRITE returns? Can I answer WANT_WRITE by repeating the same call that was called? And if WANT_READ is returned, do I need to go back to the main loop and let this select / poll / epoll take care of this? But what about the message that should be written first?

Or do I need to read a read immediately after a failed write? Then, what protects against reading bytes from the application protocol and then deals with it somewhere on the edge of the application when the real parser is sitting in mainloop?

+25
linux openssl sockets
source share
3 answers

With non-blocking sockets, SSL_WANT_READ means "wait for the socket to be readable, and then call this function again" .; on the contrary, SSL_WANT_WRITE means "wait until the socket is writable, and then call this function again." You can get either SSL_WANT_WRITE or SSL_WANT_READ from calling SSL_read() or SSL_write() .

+38
source share

Have you read the OpenSSL documentation for ssl_read and ssl_get_error yet?

ssl_read:

If the underlying BIO is blocked, SSL_read () will be returned only after the read operation is completed or an error has occurred, unless there is a revision in which SSL_ERROR_WANT_READ may occur. This behavior can be controlled using the SSL_MODE_AUTO_RETRY flag Call SSL_CTX_set_mode (3).

If the underlying BIO is not blocked, SSL_read () will also return when the underlying BIO was unable to satisfy the needs of SSL_read () to continue the operation. In this case, SSL_get_error (3) with a return value of SSL_read () will give SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE. As at any time, negotiations can be reviewed, a call to SSL_read () can also trigger a write operation! Then, the calling process must retry the call after taking the appropriate action to satisfy the SSL_read () need. The action depends on the underlying BIO. when using a non-blocking socket, nothing but select () can be used to check the required state.

ssl_get_error:

SSL_ERROR_WANT_READ, SSL_ERROR_WANT_WRITE

The operation is not completed; the same TLS / SSL I / O function should be called again later. If by that time the base BIO has readable data (if the result code is SSL_ERROR_WANT_READ) or allows data to be written (SSL_ERROR_WANT_WRITE), then some TLS / SSL protocol progress will be in place, that is, at least part of the TLS / SSL record will be read or recorded. Note that retrying can again result in an SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE state. There is no fixed upper limit for the number of iterations that may be necessary until progress becomes visible at the application protocol level.

For BIO sockets (for example, when SSL_set_fd ()), select () or poll () on the underlying socket can be used to search when the TLS / SSL I / O function should be repeated.

Caution: any TLS / SSL I / O function may result in SSL_ERROR_WANT_READ and SSL_ERROR_WANT_WRITE. In particular, SSL_read () or SSL_peek () can write data and SSL_write () can read data. This is mainly because TLS / SSL binding can occur at any time during the protocol (either a client or a server is initiated); SSL_read (), SSL_peek () and SSL_write () will handle any pending confirmations.

OpenSSL is implemented as a state machine. SSL_ERROR_WANT_READ means that more incoming data and SSL_ERROR_WANT_WRITE means that more outgoing data is required in order to make progress in the connection. If you get SSL_ERROR_WANT_WRITE in the ssl_read () operation, you need to send outgoing data or at least wait for the socket to be writable. If you get SSL_ERROR_WANT_READ in the ssl_write () operation, you need to read the input.

You should subscribe to the OpenSSL mailing list . This question is asked a lot.

+11
source share

SSL_WANT_READ means that the SSL mechanism cannot currently be encrypted for you, as it expects additional input (either as part of the initial handshake or as part of the review), so as soon as your next read is complete, ve clicked the data that came through the SSL mechanism, you can repeat the write operation.

Likewise, SSL_WANT_WRITE means that the SSL engine expects you to extract some data from it and send it to the peer.

I wrote about using OpenSSL with non-blocking and asynchronous sockets back in 2002 for the Windows Developer Journal (reprinted here ), and although this article is supposedly aimed at Windows code, the principles are the same for other platforms. This article introduces code that integrates OpenSSL with asynchronous sockets on Windows and that addresses the whole issue of SSL_WANT_READ / SSL_WANT_WRITE.

Essentially, when you get SSL_WANT_READ, you need to send outgoing data to the queue until you finish reading, and you send the new incoming data to the SSL mechanism, as soon as this happens, you can retry sending the outgoing data.

+5
source share

All Articles