Why does SSL_set_bio takes two pointers to BIO as

2020-03-26 11:34发布


SSL_set_bio uses two OpenSSL BIOs: the input BIO (rbio) and the output BIO (wbio). The first one is used when OpenSSL needs to get data from the remote side and the second one is used when OpenSSL needs to send data to remote side. Usually these two BIOs are the same (they are pointers to the same BIO object). For example, it may be a socket BIO (BIO_s_socket). When OpenSSL needs data, it receives it from that socket BIO. And it uses the same socket BIO to send data. So a single BIO object would be enough.

The only case I can think of when two different BIOs are required is when memory BIO (BIO_s_mem) is used. Memory BIO is like loopback BIO: any data that is written to memory BIO will be read from it back later in the subsequent read operations. Memory BIO is needed when an application implements data transferring by itself without using OpenSSL BIOs. The application receives data from the remote side using its own functions and then puts it to the input memory BIO so that OpenSSL can get it. And the opposite process: OpenSSL puts output data to the output memory BIO and then the application gets the data from the output BIO and sends it to the remote side using its own functions. Since two buffers (the input and the output) are required, two different memory BIOs are used for a single SSL/TLS link.

But in addition there is a BIO called BIO_s_bio which has a pipe-like functionality. A pair of such BIOs can be created. Any data written to the first BIO in the pair of BIO_s_bio objects will be read from the second BIO in the pair. And vice versa: writing data to the second BIO will result in reading this data from the first BIO. So BIO_s_bio can be used instead of BIO_s_mem. Passing a single instance of BIO_s_bio object to the SSL_set_bio function would be enough. Application receives data and writes it to its BIO in the BIO_s_bio pair. OpenSSL will then get this data from its BIO in the pair. OpenSSL writes data to its BIO in the pair, and the application gets this data from its BIO in turn.

Does SSL_set_bio need two pointers to BIOs only for using OpenSSL with memory BIO? Is there any other example where using two different BIOs in the SSL_set_bio function may be helpful?

Is BIO_s_mem needed at all if BIO_s_bio can be used instead? Are there any benefits of using BIO_s_mem instead of using BIO_s_bio?


Usually SSL/TLS uses one TCP socket for the link. In that case you can use the following function for setting fd to ssl:

SSL_set_fd(ssl, tcp_socket_fd);

But, there can be use cases where 2 unidirectional file descriptors are used instead of one TCP socket.

For example, if you want to implement TLS server as child of tcpd. Then your server's file descriptors for TCP traffic are:

  • STDIN_FILENO for input stream
  • STDOUT_FILENO for output stream

In that case SSL_set_fd() can not be used, and you can play with two BIOs:

   // not tested
   BIO* in = BIO_new_fd(STDIN_FILENO, 0);
   BIO* out = BIO_new_fd(STDOUT_FILENO, 0);
   SSL_set_bio(ssl, in, out);

Maybe it is better to use SSL_set_rfd() and SSL_set_wfd(). But that was just an example.

标签: openssl