2010-12-09 78 views
2

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

有没有人有/任何人都知道任何可能帮助我完成这样的任务的参考? TLS握手如何通过IOCP工作?

回答

7

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

每次执行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中的待处理数据。

0

你应该看看Boost.Asio

+0

Asio是否支持OpenSSL? – Gabe 2010-12-10 03:51:38

+0

是的,我发布的链接中有一些示例。 – 2010-12-10 12:59:20