20
votes

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.

6
You might try the OpenSSL user list. They sometimes get questions like this, and explain how to get more information, some possible causes and some possible fixes. As it stands, there's probably not enough information for someone to help you. SSL_read failed SSL_ERROR_SYSCALL error. - jww

6 Answers

13
votes

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).

5
votes

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.

4
votes

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);
3
votes

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

2
votes

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.

https://github.com/hashicorp/vagrant/issues/9612

0
votes

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.