Ssl_Read Failing with Ssl_Error_Syscall Error

Ssl_Read Failing with Ssl_Error_Syscall Error

We have implemented tls using openssl. While downloading larger data from server getting SSL_ERROR_SYSCALL error after receiving the some data. For smaller files I am not getting this error, able to download without any error. ERR_get_error() is showing zero for larger files.

We are using linux and c++ framework. How to find reason for the failure? What could be the reason for failure? kindly provide your suggestions.

1

6 Answers

SSL_ERROR_SYSCALL indicates that some problem happened with the underlying I/O (Should be TCP in this case). So, you can try checking with errno.

OpenSSL help says:

SSL_ERROR_SYSCALL

Some I/O error occurred. The OpenSSL error queue may contain more information on the error. If the error queue is empty (i.e. ERR_get_error() returns 0), ret can be used to find out more about the error: If ret == 0, an EOF was observed that violates the protocol. If ret == -1, the underlying BIO reported an I/O error (for socket I/O on Unix systems, consult errno for details).

7

If you look into the source code for SSL_get_error() you'll see, that it returns SSL_ERROR_SYSCALL whenever it not sure what exactly happened. It's basically default return code for "unknown" case.

For example, in my case (doing non-blocking IO with BIO):

int buf;
const int n = SSL_read(ssl, &buf, 0);
const int err = SSL_get_error(ssl, n);
const int st = ERR_get_error();

When n is 0, err will be SSL_ERROR_SYSCALL just because. However st still will be 0 indicating that there was no real error. SSL_read just returned 0 because 0 bytes was written to the buf.

However, look for errno / WSAGetLastError() values after the call for more details.

I found the issue to be my companies firewall blocking the requests. Go home and it should work

Check if you call SSL_read() with a buffer size of 0. I have made the following mistake using SSL_pending():

int waitForReadFd = nBuf < bufSize;

if (waitForReadFd)
    FD_SET(fd, &rfds);

// ...
// select

int doReadFd = FD_ISSET(fd, &rfds) || SSL_pending(ssl);

if (doReadFd)
    n = SSL_read(ssl, buf, bufSize - nBuf);

If nBuf == bufSize SSL_read() will be called with a buffer size of 0 what leads to SSL_ERROR_SYSCALL with errno == 0.

Changing the doReadFd check will avoid this problem:

int doReadFd = FD_ISSET(fd, &rfds) || nBuf < bufSize && SSL_pending(ssl);

The problem is caused by the network connection being cut and the server re-setting.

Just make sure the connection is Ok before downloading the data.

A similar problem can be seen here when using vagrant.

We encountered this error in a Go application. We were using a third party library to connect to underlying openssl library from Go. While reading data the third party library was converting the length of buffer/data to be read to C.int which is 32bits. For large data >= 2GB this lead to overflow and a negative value being passed to C.SSL_read function. It raised SSL_ERROR_SYSCALL error in that case.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Marcus Vance
Author

Marcus Vance

Marcus Vance is a cybersecurity auditor and technology writer dedicated to educating the public about online safety, data privacy regulations, enterprise security, and emerging cyber threats.