为什么SSL_set_bio需要两个指向BIO的指针作为参数?(OpenSSL“BIO_s_mem”VS“BIO_s_bio”)

ant*_*_rh 5 openssl

SSL_set_bio使用两个 OpenSSL BIO:输入 BIO ( rbio) 和输出 BIO ( wbio)。当OpenSSL需要从远程端获取数据时使用第一个,当OpenSSL需要向远程端发送数据时使用第二个。通常这两个BIO是相同的(它们是指向同一个BIO对象的指针)。例如,它可以是套接字BIO( BIO_s_socket)。当 OpenSSL 需要数据时,它从该套接字 BIO 接收数据。并且它使用相同的套接字BIO来发送数据。所以一个 BIO 对象就足够了。

我能想到的唯一需要两个不同 BIO 的情况是BIO_s_mem使用内存 BIO ( ) 时。内存 BIO 类似于环回 BIO:写入内存 BIO 的任何数据都将在后续读取操作中从其中读回。当应用程序在不使用OpenSSL BIO的情况下自行实现数据传输时,需要使用内存BIO。应用程序使用自己的函数从远程端接收数据,然后将其放入输入内存BIO中,以便OpenSSL可以获取它。相反的过程:OpenSSL将输出数据放入输出内存BIO,然后应用程序从输出BIO获取数据并使用自己的函数将其发送到远程端。由于需要两个缓冲区(输入和输出),因此两个不同的内存 BIO 用于单个 SSL/TLS 链接。

但除此之外,还有一个名为 BIO BIO_s_bio,它具有类似管道的功能。可以创建一对这样的 BIO。写入对象对中第一个 BIO 的任何数据都BIO_s_bio将从对象对中的第二个 BIO 中读取。反之亦然:向第二个 BIO 写入数据将导致从第一个 BIO 读取该数据。所以BIO_s_bio可以用来代替BIO_s_mem. BIO_s_bio将对象的单个实例传递给SSL_set_bio函数就足够了。应用程序接收数据并将其写入该BIO_s_bio对中的 BIO。然后 OpenSSL 将从该对中的 BIO 中获取此数据。OpenSSL 将数据写入该对中的 BIO,应用程序依次从其 BIO 中获取该数据。

是否SSL_set_bio仅需要两个指向 BIO 的指针才能将 OpenSSL 与内存 BIO 结合使用?是否还有其他示例在SSL_set_bio函数中使用两个不同的 BIO 可能会有所帮助?

如果可以代替的话,BIO_s_mem是否需要?使用而不是使用BIO_s_bio有什么好处吗?BIO_s_memBIO_s_bio

SKi*_*SKi 2

通常 SSL/TLS 使用一个 TCP 套接字进行链接。在这种情况下,您可以使用以下函数将 fd 设置为 ssl:

SSL_set_fd(ssl, tcp_socket_fd);
Run Code Online (Sandbox Code Playgroud)

但是,可能存在使用 2 个单向文件描述符而不是 1 个 TCP 套接字的用例。

例如,如果您想将 TLS 服务器实现为 tcpd 的子级。那么您的服务器的 TCP 流量文件描述符是:

  • STDIN_FILENO 用于输入流
  • STDOUT_FILENO 用于输出流

这样的话SSL_set_fd()就不能用了,可以用两个BIO来玩:

   // not tested
   BIO* in = BIO_new_fd(STDIN_FILENO, 0);
   BIO* out = BIO_new_fd(STDOUT_FILENO, 0);
   SSL_set_bio(ssl, in, out);
Run Code Online (Sandbox Code Playgroud)

SSL_set_rfd()也许使用和更好SSL_set_wfd()。但这只是一个例子。