简体   繁体   中英

using openssl with its unblocked bio, ssl_read return SSL_ERROR_SYSCALL and SSL_ERROR_WANT_READ

I use zeromq and openssl to write my server and client .

After successful handshake, when the client sends message to server again, the ssl_read() in server returns -1 and ssl_get_erro() returns SSL_ERROR_SYSCALL,

this situation repeats when server receives messages again. I cannot find the reason. Do i need BIO_flush()? I would really appreciate you even just give me some inspirations to work this out.


well, my program is too complicated to show. I was asked to add ssl to rpcz to improve its security (I dont know if rpcz is popular enough for most people to know. In my word ,it combines zeromq,protobuf and rpc to realize remote procedure call). So there are lots of pieces of code, I think it wont help by showing them all here.

I am trying to give more details.

After a successful handshake, when server try to decrypt the data it receives, using a method like this

`{
  //.......
  bio_write();
  //.......
  ssl_read();
}`

and it turns out that bio_write() has successfully written the data into bio by returning number of the data, but ssl_read() always retun -1. So I use ssl_get_error() to check the error number, it returns SSL_ERROR_SYSCALL, and for the next data received,it returns SSL_ERROR_WANT_READ.

hope that someone can help to explain why ssl_read returns these code? I think if the ssl connection does not handshake successfully, ssl_write() wont return a positive number. So may the problem is not the ssl connection.


add some details again

void TLSZmq::ssl_decrypt()
{
    //........
    ERR_clear_error();
    int rc = BIO_write(rbio,zmq_to_ssl->data(),zmq_to_ssl->size()); 
    ERR_get_error();
    check_ssl_err(rc); //written by myself
    //.........
    ERR_clear_error();      
    aread = SSL_read(ssl_,buffer,BUFFERSIZE);
    ERR_get_error();
    check_ssl_err(rc); //written by myself
    //..........
}

  void TLSZmq::check_ssl_err(int rc)
{
    //...................
    int err = SSL_get_error(ssl_, rc);
    if (err == SSL_ERROR_NONE)
    {
        std::cout<<"SSL_ERROR_NONE:"<<SSL_ERROR_NONE<<std::endl;
    }
    else if (err == SSL_ERROR_WANT_READ ) 
    { 
        std::cout<<"SSL_ERROR_WANT_READ:"<<SSL_ERROR_WANT_READ<<std::endl;
    }
    else if (SSL_ERROR_SYSCALL)
    {
        std::cout<<"SSL_ERROR_SYSCALL:"<<SSL_ERROR_SYSCALL<<std::endl;          

    }

    //.....................
}

I am not sure this is the right way to check the error stack or something. when SSL_ERROR_SYSCALL appears, ERR_get_error() return a strange number like 336130315, and when SSL_ERROR_WANT_READ appears, ERR_get_error() returns 0.

I also have tested that the ssl connection(SSL* ssl) which is used by decrypt procedure after handshake is as same as it used during the handshake .

er...we are talking openssl right? rc gets the return value of BIO_write() function of openssl. PS I use zeromq socket for sending message, which I have pointed out. I am confused. Does it make sense to get errno by or call perror() ?


Really thanks for your time reading this.

An SSL connection is not a decryption function and an encryption function that can be used independently. If you want a block or stream cipher, you can get one using the OpenSSL code for some of the pieces. But you can't use SSL itself that way.

It is possible to use BIO pairs to allow SSL to operate over a transport layer other than TCP. But you have to replicate the semantics of TCP -- it's complex, and the code looks nothing like the code you have above. (For example, TCP permits transmission in either direction at any time. You don't replicate that. SSL, designed to be layered on top of TCP, requires you to replicate that for it to work on some other transport.)

If you want a stream cipher, just use one.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM