2010-12-09 2 views
2

У меня есть код устаревшего кода, который использует OpenSSL для связи. Как и любой другой сеанс, он выполняет рукопожатие с использованием функций SSL, а затем зашифровывает связь через TCP. Недавно мы изменили наш код, чтобы использовать порты завершения ввода-вывода. То, как он работает, противоречит OpenSSL. В принципе, мне трудно переносить наш безопасный код связи из полного использования OpenSSL в сокеты IOCP и шифрование OpenSSL.Порты ввода-вывода ввода и 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