Порты завершения ввода-вывода и OpenSSL - PullRequest
4 голосов
/ 10 декабря 2010

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

Кто-нибудь знает / знает кто-нибудь какие-либо ссылки, которые могут помочь мне в такой задаче?Как TLS handshaking будет работать через IOCP?

Ответы [ 2 ]

8 голосов
/ 13 декабря 2010

Для того, чтобы использовать OpenSSL для шифрования, но сделать свой собственный сокет-ввод-вывод, в основном вы создаете BIO памяти, в которую вы читаете и записываете данные сокета, когда они становятся доступными, и присоединяете их к контексту SSL.

Каждый раз, когда вы выполняете вызов SSL_write, вы выполняете вызов в БИО памяти, чтобы проверить, есть ли у него данные в буфере чтения, прочитать их и отправить. И наоборот, когда данные поступают в сокет через механизм порта завершения 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 голосов
/ 10 декабря 2010

Вы должны посмотреть на Boost.Asio

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...