IO完成端口和OpenSSL

时间:2010-12-09 22:32:51

标签: c++ openssl

我有一些使用OpenSSL进行通信的遗留代码。就像任何其他会话一样,它使用SSL功能进行握手,然后通过TCP进行加密通信。我们最近更改了代码以使用IO完成端口。它的工作方式与OpenSSL相反。基本上,我很难将安全通信代码从完整的OpenSSL使用迁移到IOCP套接字和OpenSSL加密。

是否有人/任何人知道任何可能帮助我完成此类任务的参考资料? TLS握手如何在IOCP上工作?

2 个答案:

答案 0 :(得分:8)

为了使用OpenSSL进行加密,但是使用自己的套接字IO,你基本上做的是创建一个内存BIO,你可以读取和写入套接字数据,并将其附加到SSL上下文。 / p>

每次执行SSL_write调用时,都会跟进对内存BIO的调用,以查看它的读缓冲区中是否有数据,读出并发送。 相反,当数据通过您的io完成端口机制到达套接字时,您将其写入BIO并调用SSL_read以读取数据。 SSL_read可能会返回一个错误代码,指示它在握手中,这通常意味着它生成了更多要写入的数据 - 您可以通过再次读取内存BIO来处理它。


要创建我的SSL会话,我这样做:

// This creates a SSL session, and an in, and an out, memory bio and
// attaches them to the ssl session.
SSL* conn = SSL_new(ctx);
BIO* bioIn = BIO_new(BIO_s_mem());
BIO* bioOut = BIO_new(BIO_s_mem());
SSL_set_bio(conn,bioIn,bioOut);
// This tells the ssl session to start the negotiation.
SSL_set_connect_state(conn);

当我从网络层接收数据时:

// buf contains len bytes read from the socket.
BIO_write(bioIn,buf,len);
SendPendingHandshakeData();
TryResendBufferedData(); // see below
int cbPlainText;
while( cbPlainText = SSL_read(ssl,&plaintext,sizeof(plaintext)) >0)
{
  // Send the decoded data to the application
  ProcessPlaintext(plaintext,cbPlaintext);
}

当我从要发送的应用程序接收数据时 - 您需要为SSL_write做好准备,因为握手正在进行中,在这种情况下您要缓冲数据,并在接收到一些数据后尝试再次发送它

if( SSL_write(conn,buf,len) < 0)
{
  StoreDataForSendingLater(buf,len);
}
SendPendingHandshakeData();

SendPendingHandshakeData发送SSL需要发送的任何数据(握手或密文)。

while(cbPending = BIO_ctrl_pending(bioOut))
{
  int len = BIO_read(bioOut,buf,sizeof(buf));
  SendDataViaSocket(buf,len); // you fill this in here.
}

简而言之,就是这个过程。代码示例并不完整,因为我必须从更大的库中提取它们,但我相信它们足以让我们开始使用SSL。在实际代码中,当SSL_read / write / BIO_read / write失败时,可能最好调用SSL_get_error并根据结果决定做什么:SSL_ERROR_WANT_READ是重要的,并且意味着您无法SSL_write任何更多数据,因为它需要您首先在bioOut BIO中读取和发送待处理数据。

答案 1 :(得分:-1)

您应该查看Boost.Asio